This test is working fine on my host machine but fails on Serenity:
I did some digging, the issue seems to be with Serenity's strtod() implementation:
Simple program to reproduce:
#include <AK/LogStream.h>
#include <stdlib.h>
int main(int, char**)
{
double d1 = strtod("5.000000000000001", nullptr);
double d2 = strtod("5.0000000000000001", nullptr);
dbg() << (((i32)d1 == d1) ? "(i32)d1 == d1" : "(i32)d1 != d1");
dbg() << (((i32)d2 == d2) ? "(i32)d2 == d2" : "(i32)d2 != d2");
}
Serenity:
(i32)d1 != d1
(i32)d2 != d2
Linux (via Lagom):
(i32)d1 != d1
(i32)d2 == d2
Some more weird stuff happening:
> 1.0000000000000000000000000000001
1.0000
> 1.00000000000000000000000000000001
Infinity
> 1.12345678912345678912345678912345
Infinity
> 1.123456789123456789123456789123456789123456789
Infinity
That reminds me a lot of Rust's struggles with float literals. You may find these test cases helpful.
For the record: I'm having a look at whether I can write a strtod myself. Here's a peek.
Here's a few fun bits, maybe for entertainment, maybe for documentation:
4e3e4 becomes 40000.0, because the second exponent "overwrites" the first.atof thinks that 5e-3 is 5000, because atof ignores a minus sign in the exponent. strtod handles that correctly. (Also, why the duplicated code? Also, why is the exponent sign handled manually when the atoi implementation could handle it?)7e0 becomes 70.0, because the e is ignored if it is followed by only-zeros.1e-4294967296 becomes 14294967296.0, because it attempts to read 4294967296 as a positive int, this overflows, atol returns 0 out of spite (seriously), and strtod just continues as if nothing had happened.1e-599999999 becomes 0.0 correctly, but takes a lot of time for it (because it divides by 10 very, very often).return 0.0; makes more tests green than it makes red.I'll also touch up atoi and related code.
Most helpful comment
Here's a few fun bits, maybe for entertainment, maybe for documentation:
4e3e4becomes40000.0, because the second exponent "overwrites" the first.atofthinks that5e-3is5000, becauseatofignores a minus sign in the exponent.strtodhandles that correctly. (Also, why the duplicated code? Also, why is the exponent sign handled manually when theatoiimplementation could handle it?)7e0becomes70.0, because theeis ignored if it is followed by only-zeros.1e-4294967296becomes14294967296.0, because it attempts to read 4294967296 as a positive int, this overflows,atolreturns 0 out of spite (seriously), andstrtodjust continues as if nothing had happened.1e-599999999becomes0.0correctly, but takes a lot of time for it (because it divides by 10 very, very often).return 0.0;makes more tests green than it makes red.I'll also touch up
atoiand related code.