Thread overview
Full precision double to string conversion
Nov 03, 2018
Ecstatic Coder
Nov 03, 2018
Danny Arends
Nov 03, 2018
Ecstatic Coder
Nov 03, 2018
Stanislav Blinov
Nov 03, 2018
Ecstatic Coder
Nov 03, 2018
Stanislav Blinov
Nov 03, 2018
Ecstatic Coder
November 03, 2018
import std.conv;
import std.stdio;
void main()
{
    double value = -12.000123456;
    writeln( value.sizeof );
    writeln( value );
    writeln( value.to!string() );
    writeln( value.to!dstring() );
}

/*
8
-12.0001
-12.0001
-12.0001
*/

In Dart, value.toString() returns "-12.000123456".

In C#, value.ToString() returns "-12.000123456".

In D, value.to!string() returns "-12.0001" :(

How can I convert a double value -12.000123456 to its string value "-12.000123456", i.e. without loosing double-precision digits ?


November 03, 2018
On Saturday, 3 November 2018 at 12:27:19 UTC, Ecstatic Coder wrote:
> import std.conv;
> import std.stdio;
> void main()
> {
>     double value = -12.000123456;
>     writeln( value.sizeof );
>     writeln( value );
>     writeln( value.to!string() );
>     writeln( value.to!dstring() );
> }
>
> /*
> 8
> -12.0001
> -12.0001
> -12.0001
> */
>
> In Dart, value.toString() returns "-12.000123456".
>
> In C#, value.ToString() returns "-12.000123456".
>
> In D, value.to!string() returns "-12.0001" :(
>
> How can I convert a double value -12.000123456 to its string value "-12.000123456", i.e. without loosing double-precision digits ?

Specify how many digits you want with writefln:

writefln("%.8f", value);

November 03, 2018
On Saturday, 3 November 2018 at 12:45:03 UTC, Danny Arends wrote:
> On Saturday, 3 November 2018 at 12:27:19 UTC, Ecstatic Coder wrote:
>> import std.conv;
>> import std.stdio;
>> void main()
>> {
>>     double value = -12.000123456;
>>     writeln( value.sizeof );
>>     writeln( value );
>>     writeln( value.to!string() );
>>     writeln( value.to!dstring() );
>> }
>>
>> /*
>> 8
>> -12.0001
>> -12.0001
>> -12.0001
>> */
>>
>> In Dart, value.toString() returns "-12.000123456".
>>
>> In C#, value.ToString() returns "-12.000123456".
>>
>> In D, value.to!string() returns "-12.0001" :(
>>
>> How can I convert a double value -12.000123456 to its string value "-12.000123456", i.e. without loosing double-precision digits ?
>
> Specify how many digits you want with writefln:
>
> writefln("%.8f", value);

Actually, what I need is the D equivalent of the default ToString() function we have in Dart and C#.

I mean a dumb double-to-string standard library conversion function which returns a string including all the double precision digits stored in the 52 significant bits of the value, preferably with the trailing zeroes removed.

For an unknown reason, D's default double-to-string conversion function only expose the single-precision significant digits :(

November 03, 2018
On Saturday, 3 November 2018 at 13:20:22 UTC, Ecstatic Coder wrote:
> On Saturday, 3 November 2018 at 12:45:03 UTC, Danny Arends wrote:

>>> How can I convert a double value -12.000123456 to its string value "-12.000123456", i.e. without loosing double-precision digits ?
>>
>> Specify how many digits you want with writefln:
>>
>> writefln("%.8f", value);
>
> Actually, what I need is the D equivalent of the default ToString() function we have in Dart and C#.

I don't think it means what you think it means:

void main() {
    double value = -12.000123456;
    int precision = 50;

    import std.stdio;
    writefln("%.*g", precision, value);

    import std.format;
    string str = format("%.*g", precision, value);
    writeln(str);
}

Prints:

-12.000123456000000743415512260980904102325439453125
-12.000123456000000743415512260980904102325439453125

That's not quite the -12.000123456 that you'd get from C#'s ToString().

> I mean a dumb double-to-string standard library conversion function which returns a string including all the double precision digits stored in the 52 significant bits of the value, preferably with the trailing zeroes removed.

All of them? Most implementations of conversion algorithms actually stop when it's "good enough". AFAIR, D doesn't even have it's own implementation and forwards to C, unless that changed in recent years.
November 03, 2018
>> Actually, what I need is the D equivalent of the default ToString() function we have in Dart and C#.
>
> I don't think it means what you think it means:
>
> void main() {
>     double value = -12.000123456;
>     int precision = 50;
>
>     import std.stdio;
>     writefln("%.*g", precision, value);
>
>     import std.format;
>     string str = format("%.*g", precision, value);
>     writeln(str);
> }
>
> Prints:
>
> -12.000123456000000743415512260980904102325439453125
> -12.000123456000000743415512260980904102325439453125
>
> That's not quite the -12.000123456 that you'd get from C#'s ToString().

Unfortunately, but that's still better though, thanks :)

> All of them? Most implementations of conversion algorithms actually stop when it's "good enough". AFAIR, D doesn't even have it's own implementation and forwards to C, unless that changed in recent years.

What I meant was that getting too many significant digits would still be a better solution than not having them.

But indeed what I really need is a D function which gives a better decimal approximation to the provided double constant, exactly in the same way those in Dart and C# do.

Is there really no such function in D ?



November 03, 2018
On Saturday, 3 November 2018 at 17:26:19 UTC, Ecstatic Coder wrote:

>> void main() {
>>     double value = -12.000123456;
>>     int precision = 50;
>>
>>     import std.stdio;
>>     writefln("%.*g", precision, value);
>>
>>     import std.format;
>>     string str = format("%.*g", precision, value);
>>     writeln(str);
>> }
>>
>> Prints:
>>
>> -12.000123456000000743415512260980904102325439453125
>> -12.000123456000000743415512260980904102325439453125
>>
>> That's not quite the -12.000123456 that you'd get from C#'s ToString().
>
> Unfortunately, but that's still better though, thanks :)

I don't think you understood what I meant. Neither C# nor D attempt to exhaust the precision when converting, given default arguments. It's merely a matter of those defaults. The snippet above obviously provides *more* digits that the default .ToString() in C# would.

> But indeed what I really need is a D function which gives a better decimal approximation to the provided double constant, exactly in the same way those in Dart and C# do.
>
> Is there really no such function in D ?

When you call .ToString() in C# with no arguments, it assumes the "G" format specifier.

https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings?view=netframework-4.7.2#the-general-g-format-specifier

So for a double, it will use 15-digit precision. D's to!string simply uses lower default. If you want the exact same behavior as in C#, you can do this:

string toStringLikeInCSharp(double value) {
    import std.format : format;
    return format("%.15G", value);
}

void main() {
    double value = -12.000123456;
    import std.stdio;
    writeln(value.toStringLikeInCSharp); // prints: -12.000123456
}
November 03, 2018
On Saturday, 3 November 2018 at 18:04:07 UTC, Stanislav Blinov wrote:
> On Saturday, 3 November 2018 at 17:26:19 UTC, Ecstatic Coder wrote:
>
>>> void main() {
>>>     double value = -12.000123456;
>>>     int precision = 50;
>>>
>>>     import std.stdio;
>>>     writefln("%.*g", precision, value);
>>>
>>>     import std.format;
>>>     string str = format("%.*g", precision, value);
>>>     writeln(str);
>>> }
>>>
>>> Prints:
>>>
>>> -12.000123456000000743415512260980904102325439453125
>>> -12.000123456000000743415512260980904102325439453125
>>>
>>> That's not quite the -12.000123456 that you'd get from C#'s ToString().
>>
>> Unfortunately, but that's still better though, thanks :)
>
> I don't think you understood what I meant. Neither C# nor D attempt to exhaust the precision when converting, given default arguments. It's merely a matter of those defaults. The snippet above obviously provides *more* digits that the default .ToString() in C# would.
>
>> But indeed what I really need is a D function which gives a better decimal approximation to the provided double constant, exactly in the same way those in Dart and C# do.
>>
>> Is there really no such function in D ?
>
> When you call .ToString() in C# with no arguments, it assumes the "G" format specifier.
>
> https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings?view=netframework-4.7.2#the-general-g-format-specifier
>
> So for a double, it will use 15-digit precision. D's to!string simply uses lower default. If you want the exact same behavior as in C#, you can do this:
>
> string toStringLikeInCSharp(double value) {
>     import std.format : format;
>     return format("%.15G", value);
> }
>
> void main() {
>     double value = -12.000123456;
>     import std.stdio;
>     writeln(value.toStringLikeInCSharp); // prints: -12.000123456
> }

This version perfectly gets the job done!

Thanks a lot for your help :)