Stephanie Evert
2025-Mar-09 18:06 UTC
[R] Number changed weirdly when converting to numeric
For once, that doesn't seem to be the issue here. The bug only seems to happen on arm64 and doesn't reproduce on x86_64 hardware.> x <- as.numeric("-177253333.333333343267441") > sprintf("%.15f", x)[1] "-177253333.333333373069763" This is the number adjacent to -177253333.333333343267441 in IEEE 754.> writeBin(x, raw(8))[1] ac aa aa aa 57 21 a5 c1 If you look at the hexadecimal representation, the least significant bit appears to be off by one: the first byte should be 0xAB rather than 0xAC (according to online calculators such as https://numeral-systems.com/ieee-754-converter/). Seems that decimal-to-float conversion has a bug on arm64. Note that I get the same result with> x <- -177253333.333333343267441so it's not specific to as.numeric(). Best, Stephanie> On 9 Mar 2025, at 18:46, Jeff Newmiller via R-help <r-help at r-project.org> wrote: > > https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f > > https://0.30000000000000004.com/ > > On March 9, 2025 10:12:47 AM PDT, Christofer Bogaso <bogaso.christofer at gmail.com> wrote: >> Hi, >> >> I have below simple conversion >> >>> sprintf("%0.15f", as.numeric("-177253333.333333343267441")) >> >> [1] "-177253333.333333373069763" >> >> I could not figure out why the input and output is different? >> >> Clearly this conversion is incorrect. Is there any way to convert to >> numerical properly? >> >>> sessionInfo() >> >> R version 4.4.0 (2024-04-24) >> >> Platform: aarch64-apple-darwin20 >> >> Running under: macOS 15.3.1 >> >> >> Matrix products: default >> >> BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib >> >> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; >> LAPACK version 3.12.0 >> >> >> locale: >> >> [1] C/UTF-8/C/C/C/C >> >> >> time zone: Asia >> >> tzcode source: internal >> >> >> attached base packages: >> >> [1] stats graphics grDevices utils datasets methods base >> >> >> loaded via a namespace (and not attached): >> >> [1] compiler_4.4.0 >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. > > -- > Sent from my phone. Please excuse my brevity. > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide https://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.[[alternative HTML version deleted]]
This may be way off the mark, but is it possible that the ARM machine is using the "new" IEEE-754 arithmetic that does not have 80 bit extended? The standard was changed (in ways to allow non-compliant systems to be compliant) because ARM does not have the hardware registers. There are reasons why this might be sensible, but we need more awareness of the consequences to avoid some of the resulting changes in results. I've had to "fix" things that weren't broken because M1 and later Macs gave different outputs, actually not in my code but in vignettes where I compared to other packages. Cheers, John Nash (who actually was part of 1985 IEEE 754 committee, though a VERY minor player) On 2025-03-09 14:06, Stephanie Evert wrote:> For once, that doesn't seem to be the issue here. The bug only seems to happen on arm64 and doesn't reproduce on x86_64 hardware. > >> x <- as.numeric("-177253333.333333343267441") >> sprintf("%.15f", x) > [1] "-177253333.333333373069763" > > This is the number adjacent to -177253333.333333343267441 in IEEE 754. > >> writeBin(x, raw(8)) > [1] ac aa aa aa 57 21 a5 c1 > > If you look at the hexadecimal representation, the least significant bit appears to be off by one: the first byte should be 0xAB rather than 0xAC (according to online calculators such as https://numeral-systems.com/ieee-754-converter/). > > Seems that decimal-to-float conversion has a bug on arm64. Note that I get the same result with > >> x <- -177253333.333333343267441 > > so it's not specific to as.numeric(). > > Best, > Stephanie > > > > >> On 9 Mar 2025, at 18:46, Jeff Newmiller via R-help <r-help at r-project.org> wrote: >> >> https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f >> >> https://0.30000000000000004.com/ >> >> On March 9, 2025 10:12:47 AM PDT, Christofer Bogaso <bogaso.christofer at gmail.com> wrote: >>> Hi, >>> >>> I have below simple conversion >>> >>>> sprintf("%0.15f", as.numeric("-177253333.333333343267441")) >>> >>> [1] "-177253333.333333373069763" >>> >>> I could not figure out why the input and output is different? >>> >>> Clearly this conversion is incorrect. Is there any way to convert to >>> numerical properly? >>> >>>> sessionInfo() >>> >>> R version 4.4.0 (2024-04-24) >>> >>> Platform: aarch64-apple-darwin20 >>> >>> Running under: macOS 15.3.1 >>> >>> >>> Matrix products: default >>> >>> BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib >>> >>> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; >>> LAPACK version 3.12.0 >>> >>> >>> locale: >>> >>> [1] C/UTF-8/C/C/C/C >>> >>> >>> time zone: Asia >>> >>> tzcode source: internal >>> >>> >>> attached base packages: >>> >>> [1] stats graphics grDevices utils datasets methods base >>> >>> >>> loaded via a namespace (and not attached): >>> >>> [1] compiler_4.4.0 >>> >>> ______________________________________________ >>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >>> https://stat.ethz.ch/mailman/listinfo/r-help >>> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html >>> and provide commented, minimal, self-contained, reproducible code. >> >> -- >> Sent from my phone. Please excuse my brevity. >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide https://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
Out of curiosity, what does atof() do on that platform? What does the following C program do on arm64? (I don't know exactly what R does to coerce character to double, but this is what I would guess ...) #include <stdio.h> #include <stdlib.h> int main(void) { const char *str = "-177253333.333333343267441"; double x = atof(str); printf("%0.15f\n", x); return 0; } To my surprise, apparently R doesn't use stdlib to convert. From https://github.com/r-devel/r-svn/blob/bb64b28d8cc2e2863eb664e7f83b0a7206b4b1d4/src/main/util.c#L2087C1-L2107: /* ... use our own strtod/atof to mitigate effects of setting LC_NUMERIC Also allows complete control of which non-numeric strings are accepted; e.g. glibc allows NANxxxx, macOS NAN(s), this accepts "NA". ... */ Should this be escalated to r-devel (or r-bugzilla)? Nothing pops out at me from the recent NEWS ... Ben Bolker On 3/9/25 14:06, Stephanie Evert wrote:> For once, that doesn't seem to be the issue here. The bug only seems to happen on arm64 and doesn't reproduce on x86_64 hardware. > >> x <- as.numeric("-177253333.333333343267441") >> sprintf("%.15f", x) > [1] "-177253333.333333373069763" > > This is the number adjacent to -177253333.333333343267441 in IEEE 754. > >> writeBin(x, raw(8)) > [1] ac aa aa aa 57 21 a5 c1 > > If you look at the hexadecimal representation, the least significant bit appears to be off by one: the first byte should be 0xAB rather than 0xAC (according to online calculators such as https://numeral-systems.com/ieee-754-converter/). > > Seems that decimal-to-float conversion has a bug on arm64. Note that I get the same result with > >> x <- -177253333.333333343267441 > > so it's not specific to as.numeric(). > > Best, > Stephanie > > > > >> On 9 Mar 2025, at 18:46, Jeff Newmiller via R-help <r-help at r-project.org> wrote: >> >> https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f >> >> https://0.30000000000000004.com/ >> >> On March 9, 2025 10:12:47 AM PDT, Christofer Bogaso <bogaso.christofer at gmail.com> wrote: >>> Hi, >>> >>> I have below simple conversion >>> >>>> sprintf("%0.15f", as.numeric("-177253333.333333343267441")) >>> >>> [1] "-177253333.333333373069763" >>> >>> I could not figure out why the input and output is different? >>> >>> Clearly this conversion is incorrect. Is there any way to convert to >>> numerical properly? >>> >>>> sessionInfo() >>> >>> R version 4.4.0 (2024-04-24) >>> >>> Platform: aarch64-apple-darwin20 >>> >>> Running under: macOS 15.3.1 >>> >>> >>> Matrix products: default >>> >>> BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib >>> >>> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; >>> LAPACK version 3.12.0 >>> >>> >>> locale: >>> >>> [1] C/UTF-8/C/C/C/C >>> >>> >>> time zone: Asia >>> >>> tzcode source: internal >>> >>> >>> attached base packages: >>> >>> [1] stats graphics grDevices utils datasets methods base >>> >>> >>> loaded via a namespace (and not attached): >>> >>> [1] compiler_4.4.0 >>> >>> ______________________________________________ >>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >>> https://stat.ethz.ch/mailman/listinfo/r-help >>> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html >>> and provide commented, minimal, self-contained, reproducible code. >> >> -- >> Sent from my phone. Please excuse my brevity. >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide https://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.-- Dr. Benjamin Bolker Professor, Mathematics & Statistics and Biology, McMaster University Director, School of Computational Science and Engineering * E-mail is sent at my convenience; I don't expect replies outside of working hours.
Jeff Newmiller
2025-Mar-09 19:31 UTC
[R] Number changed weirdly when converting to numeric
I now see more clearly what the complaint is. That said, you should ALWAYS be prepared for the round trip between binary and string forms of floating point to accrue rounding error because floating point is intrinsically approximate. While there are examples of floating point numbers that can reliably do that round trip exactly (e.g. integers shorter than the mantissa), in general you should be prepared for such "inexact" results. John Nash's point that IEEE754 has been relaxed is reinforcement that they want users to be prepared for differences around the least significant bits... but the principle is mathematically intrinsic to the scope of floating point numbers whether the standard says so or not. On March 9, 2025 11:06:17 AM PDT, Stephanie Evert <stefanML at collocations.de> wrote:>For once, that doesn't seem to be the issue here. The bug only seems to happen on arm64 and doesn't reproduce on x86_64 hardware. > >> x <- as.numeric("-177253333.333333343267441") >> sprintf("%.15f", x) >[1] "-177253333.333333373069763" > >This is the number adjacent to -177253333.333333343267441 in IEEE 754. > >> writeBin(x, raw(8)) >[1] ac aa aa aa 57 21 a5 c1 > >If you look at the hexadecimal representation, the least significant bit appears to be off by one: the first byte should be 0xAB rather than 0xAC (according to online calculators such as https://numeral-systems.com/ieee-754-converter/). > >Seems that decimal-to-float conversion has a bug on arm64. Note that I get the same result with > >> x <- -177253333.333333343267441 > >so it's not specific to as.numeric(). > >Best, >Stephanie > > > > >> On 9 Mar 2025, at 18:46, Jeff Newmiller via R-help <r-help at r-project.org> wrote: >> >> https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f >> >> https://0.30000000000000004.com/ >> >> On March 9, 2025 10:12:47 AM PDT, Christofer Bogaso <bogaso.christofer at gmail.com> wrote: >>> Hi, >>> >>> I have below simple conversion >>> >>>> sprintf("%0.15f", as.numeric("-177253333.333333343267441")) >>> >>> [1] "-177253333.333333373069763" >>> >>> I could not figure out why the input and output is different? >>> >>> Clearly this conversion is incorrect. Is there any way to convert to >>> numerical properly? >>> >>>> sessionInfo() >>> >>> R version 4.4.0 (2024-04-24) >>> >>> Platform: aarch64-apple-darwin20 >>> >>> Running under: macOS 15.3.1 >>> >>> >>> Matrix products: default >>> >>> BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib >>> >>> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; >>> LAPACK version 3.12.0 >>> >>> >>> locale: >>> >>> [1] C/UTF-8/C/C/C/C >>> >>> >>> time zone: Asia >>> >>> tzcode source: internal >>> >>> >>> attached base packages: >>> >>> [1] stats graphics grDevices utils datasets methods base >>> >>> >>> loaded via a namespace (and not attached): >>> >>> [1] compiler_4.4.0 >>> >>> ______________________________________________ >>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >>> https://stat.ethz.ch/mailman/listinfo/r-help >>> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html >>> and provide commented, minimal, self-contained, reproducible code. >> >> -- >> Sent from my phone. Please excuse my brevity. >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. >-- Sent from my phone. Please excuse my brevity.