Printing shortest decimal form of floating point number with Mir

9il ilyayaroshenko at gmail.com
Mon Dec 14 06:47:32 UTC 2020


Hi all,

Generic version of Ryu algorithm [1] was ported to D, well 
optimized, and adopted to mir packages.

It allows printing the shortest (scientific) decimal form of a 
floating-point number that if it is converted back would produce 
the same floating-point number.

The update requires mir-algorithm [2] >=3.10.13

@safe pure nothrow unittest
{
     import mir.conv: to;
     assert(12.3.to!string == "1.23e1");
     assert(12.3456789.to!string == "1.23456789e1");

     // CTFE-able
     static assert(12.3456789.to!string == "1.23456789e1");
}

@safe pure @nogc unittest
{
     // @nogc
     import mir.conv: to;
     import mir.small_string;
     assert(12.3.to!(SmallString!32) == "1.23e1");
     assert(12.3456789.to!(SmallString!32) == "1.23456789e1");
}

@safe pure @nogc nothrow unittest
{
     // @nogc
     import mir.format;
     stringBuf buffer;
     auto data = buffer << 12.3 << ", " << 12.3456789 << getData;
     assert(data == "1.23e1, 1.23456789e1");
}

Floating-point numbers can be converted to stack-allocated 
decimal numbers.

     @safe pure nothrow @nogc
     unittest
     {
         // float and double can be used to construct Decimal of 
any length
         auto decimal64 = Decimal!1(-1.235e-7);
         assert(decimal64.exponent == -10);
         assert(decimal64.coefficient == -1235);

         // real number may need Decimal at least length of 2
         auto decimal128 = Decimal!2(-1.235e-7L);
         assert(decimal128.exponent == -10);
         assert(decimal128.coefficient == -1235);

         decimal128 = Decimal!2(1234e3f);
         assert(decimal128.exponent == 3);
         assert(decimal128.coefficient == 1234);
     }


Recent releases of ASDF [3] and Mir Ion [4] use this formatting 
by default. It allows performing JSON serialization without loss 
of precision.

Note that D's compiler floating-point literals parsing and Phobos 
floating-point literals parsing are not precise [5,6,7,8]. It is 
recommended to use Mir's to!double/float/real to convert 
floating-point numbers from a string.

The work has been sponsored by Symmetry Investments and Kaleidic 
Associates.

Kind regards,
Ilya

[1] https://github.com/ulfjack/ryu
[2] http://mir-algorithm.libmir.org/
[3] http://asdf.libmir.org/
[4] http://mir-ion.libmir.org/
[5] https://issues.dlang.org/show_bug.cgi?id=20951
[6] https://issues.dlang.org/show_bug.cgi?id=20952
[7] https://issues.dlang.org/show_bug.cgi?id=20953
[8] https://issues.dlang.org/show_bug.cgi?id=20967




More information about the Digitalmars-d-announce mailing list