Why does gawk (sometimes?) think 2.0e-318 > 2.0?

There are several issues with processing such small numbers (2e-318) in awk.

  • First, the input needs to be converted to a number before using it. That is usually done by adding 0. So, you need something like:

    val=0+$1
    
  • Second, Normal double precision floats (53 bit mantissa and 11 bit exponent) The 11 bit width of the exponent allows the representation of numbers between 10e-308 and 10e308, so, normal floats will not be able to represent such numbers.

    $ echo '1e-307 1e-308' | awk '{print $1,$1+0,$2,$2+0}'
    1e-307 1e-307 1e-308 0
    

    Default GNU awk will not accept (normal) values below 1e-308.

  • Third, The default conversion format for awk (both CNVFMT and OFMT) are set to "%.6g". Numbers with more than 6 significant figures will be truncated. To get more significant figures: ask for them. Like %.15g for 15 (don't ask for more than 17 for a 53 bit mantissa, it could lie).

  • Fourth, It is better to set the first value of max to the first input. Setting max to 0 will fail if input has a negative maximum.


If you are using GNU awk and it has been compiled with arbitrary precision you can use:

$ printf '%s\n' 2e-318 2e-317 2e-307 2e-308 2e-319 | 
    awk -M -v PREC=100     'BEGIN{OFMT="%.15g"};
        {val=0+$1};
        NR==1{max=val};
        {print($1,val,max)};
        val>max{max=val}
        END{print max}'

2e-318 2e-318 2e-318
2e-317 2e-317 2e-318
2e-307 2e-307 2e-317
2e-308 2e-308 2e-307
2e-319 2e-319 2e-307
2e-307 

Or simplified to your use case:

awk -M -v PREC=100 '
    BEGIN{OFMT="%.15g"};    # allow more than 6 figures
    {val=0+$1};             # convert input to a (float) number.
    NR==1{max=val};         # On the first line, set the max value.
    val>max{max=val}        # On every entry keep track of the max.
    END{print max}          # At the end, print the max.
    '  file                 # file with input (one per line).