Closed timotheecour closed 4 years ago
The amount of research you did for this regression issue is amazing! 👏
[0.10000000000000001,0.20000000000000001,0.29999999999999999,0.40000000000000002,0.5,0.59999999999999998,0.69999999999999996,0.80000000000000004,0.90000000000000002]
this will blow up size of json files
Correction, this will blow up size for json, if the value comes from a handwritten decimal number. To my experience the majority of json number data doesn't come from floating point numbers entered manually in decimal.
this may break other people's tests that relied on stringifications of simple looking numbers
True. And I am sorry for that.
Regarding the output of [0.10000000000000001,0.20000000000000001,0.29999999999999999,0.40000000000000002,0.5,0.59999999999999998,0.69999999999999996,0.80000000000000004,0.90000000000000002]
instead of [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]
, I personally think this is an improvement. It is a very common mistake from beginners to think 0.1 * 10 == 1
, which is not the case. When echo 0.1
does print 0.10000000000000001
instead of 0.1
it might be clear that 0.1 * 10
isn't 1
. In other words I think printing 0.1
as 0.1
precisely is a lie from the language, because the internal value isn't 0.1
precisely.
regarding printf("%g\n", a)
, this one doesn't survive the roundtrip.
#include <math.h>
#include <stdio.h>
int main() {
double f = 0.1;
for(int i = 0; i < 100; ++i) {
printf("%g\n", f);
f = nextafter(f, 100);
}
}
output: only 0.1
, nothing else.
same with C++
#include <cmath>
#include <iostream>
using namespace std;
int main() {
double f = 0.1;
for(int i = 0; i < 100; ++i) {
cout << f << endl;
f = nextafter(f, 100);
}
}
I personally think this is an improvement. It is a very common mistake from beginners to think 0.1 * 10 == 1, which is not the case
beginners need to learn about FP semantics. Just like in any language.
regarding printf("%g\n", a), this one doesn't survive the roundtrip.
there's no roundtrip here. A language's default echo
command shouldn't be used for serialization; the roundtrip is for serialization (such as json/protobuf etc).
In any case https://github.com/nim-lang/Nim/issues/13365 (ryu) is the way forward, and would give you the "best of both worlds":
echo
itself to be rountrip-safe (like print in python), although this is a separate issue from doing it for things explicitly meant for serializationsince #13276 has been reverted, I'm gonna close this issue; followup work is to implement https://github.com/nim-lang/Nim/issues/13365
beginners need to learn about FP semantics. Just like in any language.
That works best if the language is honest about FP
there's no roundtrip here.
Whatever...
the recently merged https://github.com/nim-lang/Nim/pull/13276 introduced the regression /cc @krux02
that PR commented out some tests and changed some numbers for preexisting tests in tests/system/tostring.nim to deal with the fact that numbers now print weirdly; this will likely break other people's tests in the wild
pretty much no other language I know of does that, and for good reason:
python, D, C, C++, go, node js, matlab, octave, java...
yet they can handle serialization/deserialization roundtrip just fine, and aren't any less correct; printing 0.6 as 0.6 does not imply any less precision !
Example
Current Output
Expected Output
Additional Information
that PR aimed to fix https://github.com/nim-lang/Nim/issues/13196 but IMO there should be a better fix that doesn't introduce this regression. EDIT: indeed, see https://github.com/nim-lang/Nim/pull/13364
Indeed, other languages I've tried don't have that serialization/deserialization round-trip issue;
and pretty much all languages I'm familiar with print float literals like 0.4 as simply 0.4 (using default printing command):
python
D
void main(){ auto a = 0.4; writeln(a); assert(a.to!string == "0.4"); auto x = 0.12345678901234567890123456789; auto x2 = parseJSON(JSONValue(x).to!string).floating(); assert(x2 == x); }
go
matlab / octave: ditto
node js: ditto
consequences
this may break other people's tests that relied on stringifications of simple looking numbers like
echo (0.4, "foo")
this will blow up size of json files which impacts performance etc
now shows:
this affects nim doc runnableExamples, eg:
shows as:
now prints:
proposal