bug-gawk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug-gawk] gawk erroneous comparison with large negative exponents


From: Andrew J. Schorr
Subject: Re: [bug-gawk] gawk erroneous comparison with large negative exponents
Date: Mon, 13 Apr 2015 22:51:58 -0400
User-agent: Mutt/1.5.23 (2014-03-12)

Hi,

On Mon, Apr 13, 2015 at 10:40:21AM +0300, Aharon Robbins wrote:
> Ultimately, gawk relies on the C library strtod() function to convert
> a string value to a number, and since an exponent of -308 is out of
> range, strtod() fails to do.  Thus, gawk treats 1e-308 as a string and
> does a string comparison to 0.5.  This fails.

It's interesting, and perhaps a bit confusing, that the strtod call
actually returns the subnormal value and sets errno to ERANGE.  As a result,
gawk decides that the string is not numeric, but the NODE's numeric value is
actually populated with the subnormal value:

bash-4.2$ for i in `seq 305 330` ; do echo 1.0e-$i; done | gawk 'BEGIN {c = 
0.5} {printf "%s < %g = %d; %s -> %.10g\n", $1, c, ($1 < c), $1, $1}'
1.0e-305 < 0.5 = 1; 1.0e-305 -> 1e-305
1.0e-306 < 0.5 = 1; 1.0e-306 -> 1e-306
1.0e-307 < 0.5 = 1; 1.0e-307 -> 1e-307
1.0e-308 < 0.5 = 0; 1.0e-308 -> 1e-308
1.0e-309 < 0.5 = 0; 1.0e-309 -> 1e-309
1.0e-310 < 0.5 = 0; 1.0e-310 -> 1e-310
1.0e-311 < 0.5 = 0; 1.0e-311 -> 1e-311
1.0e-312 < 0.5 = 0; 1.0e-312 -> 1e-312
1.0e-313 < 0.5 = 0; 1.0e-313 -> 1e-313
1.0e-314 < 0.5 = 0; 1.0e-314 -> 1e-314
1.0e-315 < 0.5 = 0; 1.0e-315 -> 9.999999985e-316
1.0e-316 < 0.5 = 0; 1.0e-316 -> 9.999999837e-317
1.0e-317 < 0.5 = 0; 1.0e-317 -> 1.000000231e-317
1.0e-318 < 0.5 = 0; 1.0e-318 -> 9.999987485e-319
1.0e-319 < 0.5 = 0; 1.0e-319 -> 9.999888672e-320
1.0e-320 < 0.5 = 0; 1.0e-320 -> 9.999888672e-321
1.0e-321 < 0.5 = 0; 1.0e-321 -> 9.980126046e-322
1.0e-322 < 0.5 = 0; 1.0e-322 -> 9.881312917e-323
1.0e-323 < 0.5 = 0; 1.0e-323 -> 9.881312917e-324
1.0e-324 < 0.5 = 0; 1.0e-324 -> 0
1.0e-325 < 0.5 = 0; 1.0e-325 -> 0
1.0e-326 < 0.5 = 0; 1.0e-326 -> 0
1.0e-327 < 0.5 = 0; 1.0e-327 -> 0
G.0e-328 < 0.5 = 0; 1.0e-328 -> 0
1.0e-329 < 0.5 = 0; 1.0e-329 -> 0
1.0e-330 < 0.5 = 0; 1.0e-330 -> 0

> If perl handles this differently, that's great, but awk doesn't work
> that way. :-)  I believe that this is pretty clearly documented.

Here's what I see in perl:

bash-4.3$ for i in `seq 305 330` ; do echo 1.0e-$i; done | perl -e '$c = 0.5; 
while (<>) {chomp; printf "%s < %g = %d; %s -> %10g\n", $_, $c, ($_ < $c), $_, 
$_;}'
1.0e-305 < 0.5 = 1; 1.0e-305 ->     1e-305
1.0e-306 < 0.5 = 1; 1.0e-306 ->     1e-306
1.0e-307 < 0.5 = 1; 1.0e-307 ->     1e-307
1.0e-308 < 0.5 = 1; 1.0e-308 ->     1e-308
1.0e-309 < 0.5 = 1; 1.0e-309 ->          0
1.0e-310 < 0.5 = 1; 1.0e-310 ->          0
1.0e-311 < 0.5 = 1; 1.0e-311 ->          0
1.0e-312 < 0.5 = 1; 1.0e-312 ->          0
1.0e-313 < 0.5 = 1; 1.0e-313 ->          0
1.0e-314 < 0.5 = 1; 1.0e-314 ->          0
1.0e-315 < 0.5 = 1; 1.0e-315 ->          0
1.0e-316 < 0.5 = 1; 1.0e-316 ->          0
1.0e-317 < 0.5 = 1; 1.0e-317 ->          0
1.0e-318 < 0.5 = 1; 1.0e-318 ->          0
1.0e-319 < 0.5 = 1; 1.0e-319 ->          0
1.0e-320 < 0.5 = 1; 1.0e-320 ->          0
1.0e-321 < 0.5 = 1; 1.0e-321 ->          0
1.0e-322 < 0.5 = 1; 1.0e-322 ->          0
1.0e-323 < 0.5 = 1; 1.0e-323 ->          0
1.0e-324 < 0.5 = 1; 1.0e-324 ->          0
1.0e-325 < 0.5 = 1; 1.0e-325 ->          0
1.0e-326 < 0.5 = 1; 1.0e-326 ->          0
1.0e-327 < 0.5 = 1; 1.0e-327 ->          0
1.0e-328 < 0.5 = 1; 1.0e-328 ->          0
1.0e-329 < 0.5 = 1; 1.0e-329 ->          0
1.0e-330 < 0.5 = 1; 1.0e-330 ->          0

I'm not sure why the comparison succeeds in perl, but I don't think it really
understands these numeric values properly.  For example:


bash-4.2$ for i in `seq 305 310` ; do echo 1.0e-$i; done | perl -e '$c = 
1.0e-308; while (<>) {chomp; printf "%s < %g = %d; %s -> %10g\n", $_, $c, ($_ < 
$c), $_, $_;}'
1.0e-305 < 1e-308 = 0; 1.0e-305 ->     1e-305
1.0e-306 < 1e-308 = 0; 1.0e-306 ->     1e-306
1.0e-307 < 1e-308 = 0; 1.0e-307 ->     1e-307
1.0e-308 < 1e-308 = 0; 1.0e-308 ->     1e-308
1.0e-309 < 1e-308 = 1; 1.0e-309 ->          0
1.0e-310 < 1e-308 = 1; 1.0e-310 ->          0
bash-4.2$ for i in `seq 305 310` ; do echo 1.0e-$i; done | perl -e '$c = 
1.0e-309; while (<>) {chomp; printf "%s < %g = %d; %s -> %10g\n", $_, $c, ($_ < 
$c), $_, $_;}'
1.0e-305 < 0 = 0; 1.0e-305 ->     1e-305
1.0e-306 < 0 = 0; 1.0e-306 ->     1e-306
1.0e-307 < 0 = 0; 1.0e-307 ->     1e-307
1.0e-308 < 0 = 0; 1.0e-308 ->     1e-308
1.0e-309 < 0 = 0; 1.0e-309 ->          0
1.0e-310 < 0 = 0; 1.0e-310 ->          0

Regarding gawk, this does raise the question of whether node.c:r_force_number
should force the numeric value to zero when strtod sets errno.

Regards,
Andy



reply via email to

[Prev in Thread] Current Thread [Next in Thread]