parse_string(string(x)) does not return x for any bigfloat, and fpprintprec does not fix it
Maxima 5.49post, SBCL 2.6.7.
A bigfloat at fpprec 16 carries 56 bits, about 16.9 decimal digits, but only 16 are printed, so the printed form cannot reconstruct the value. Doubles round trip correctly, so this is specific to bigfloats.
(%i1) display2d:false$
(%i2) load(stringproc)$
(%i3) block([fpprec:16], block([x: bfloat(1/3)],
[string(x), is(equal(parse_string(string(x)), x)), parse_string(string(x)) - x]));
(%o3) ["3.333333333333333b-1",false,-3.469446951953614b-17]
(%i4) block([fpprec:16, fpprintprec:20], block([x: bfloat(1/3)],
[string(x), is(equal(parse_string(string(x)), x))]));
(%o4) ["3.333333333333333b-1",false]
(%i5) block([x: 1/3.0], [string(x), is(equal(parse_string(string(x)), x))]);
(%o5) ["0.3333333333333333",true]
(%i6) block([fpprec:20], map(lambda([e], [string(e), is(equal(parse_string(string(e)), e))]),
[bfloat(%pi), bfloat(1)/7, bfloat(2)^-60]));
(%o6) [["3.1415926535897932385b0",false],["1.4285714285714285714b-1",false],
["8.6736173798840354721b-19",false]]
Expected: every entry of (%o3), (%o4) and (%o6) should report true, as the float case in (%o5) does.
The relative error introduced by the round trip is about 1e-16 at fpprec 16, and the failure occurs at every fpprec tested (16, 20, 30, 50) for every bigfloat tested. (%o4) shows raising fpprintprec does not print more digits.
Consequence: writing bigfloats to a file and reading them back silently changes them, so save/load-style workflows and any text interchange lose the low digits.
This is as specified:
The specified behavior for floats is different from that of bfloats:
The problem is that there is currently no way to specify that bigfloat be printed readably.
One convention that could work is that if
fpprintprec>fpprec, then bfloats are printed readably.Readable printing is a delicate problem, and I'm not sure how much work it would take to add that to bfloat printing. See https://kurtstephens.com/files/p372-steele.pdf