[Rd] Very small numbers in hexadecimal notation parsed as zero
Florent Angly
florent.angly at gmail.com
Tue Dec 20 13:26:36 CET 2016
Hi all,
I have noticed incorrect parsing of very small hexadecimal numbers
like "0x1.00000000d0000p-987". Such a hexadecimal representation can
can be produced by sprintf() using the %a flag. The return value is
incorrectly reported as 0 when coercing these numbers to double using
as.double()/as.numeric(), as illustrated in the three examples below:
as.double("0x1.00000000d0000p-987") # should be 7.645296e-298
as.double("0x1.0000000000000p-1022") # should be 2.225074e-308
as.double("0x1.f89fc1a6f6613p-974") # should be 1.23456e-293
The culprit seems to be the src/main/util.c:R_strtod function and in
some cases, removing the zeroes directly before the 'p' leads to
correct parsing:
as.double("0x1.00000000dp-987") # 7.645296e-298, as expected
as.double("0x1.p-1022") # 2.225074e-308, as expected
I wrote a small program (in a file called "strtod.c") to compare the R
stdtod implementation to a C implementation. The C implementation
never reported 0 in the examples given above:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *string, *stopstring;
double x;
string = "0x1.00000000d0000p-987";
x = strtod(string, &stopstring);
printf("string = \"%s\"\n", string);
printf("strtod = %.17g\n\n", x);
string = "0x1.00000000dp-987";
x = strtod(string, &stopstring);
printf("string = \"%s\"\n", string);
printf("strtod = %.17g\n\n", x);
}
$ gcc -o strtod.exe strtod.c
$ ./strtod.exe
string = "0x1.00000000d0000p-987"
strtod = 7.6452955642246671e-298
string = "0x1.00000000dp-987"
strtod = 7.6452955642246671e-298
string = "0x1.0000000000000p-1022"
strtod = 2.2250738585072014e-308
string = "0x1.p-1022"
strtod = 2.2250738585072014e-308
string = "0x1.f89fc1a6f6613p-974"
strtod = 1.23456e-293
My sessionInfo() returns:
R version 3.3.2 (2016-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
locale:
[1] LC_COLLATE=German_Switzerland.1252
LC_CTYPE=German_Switzerland.1252
LC_MONETARY=German_Switzerland.1252 LC_NUMERIC=C
LC_TIME=German_Switzerland.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
Regards,
Florent
More information about the R-devel
mailing list