Jump to page: 1 2
Thread overview
problem with std.variant rounding
Apr 28, 2017
Suliman
Apr 28, 2017
Suliman
Apr 28, 2017
H. S. Teoh
May 02, 2017
Suliman
May 02, 2017
Suliman
Apr 28, 2017
kinke
Apr 28, 2017
Suliman
April 28, 2017
I am using https://github.com/mysql-d/mysql-native
It's return from DB variant data-type.

My DB include value: 56.051151 (double type in DB)

I need to extract it. I tried several variants:

writeln(point[3].coerce!float);
writeln(point[3].coerce!string);
writeln(point[3].coerce!double);

but all of them return me it as: 56.0512

How to return exactly 56.051151 ?
April 28, 2017
On Friday, 28 April 2017 at 15:45:25 UTC, Suliman wrote:
> I am using https://github.com/mysql-d/mysql-native
> It's return from DB variant data-type.
>
> My DB include value: 56.051151 (double type in DB)
>
> I need to extract it. I tried several variants:
>
> writeln(point[3].coerce!float);
> writeln(point[3].coerce!string);
> writeln(point[3].coerce!double);
>
> but all of them return me it as: 56.0512
>
> How to return exactly 56.051151 ?

import std.stdio;
import std.variant;

void main()
{
	Variant b = 56.051151;
	float x = b.coerce!float;
	writeln(x);
}

>56.0512
April 28, 2017
On Friday, 28 April 2017 at 16:24:55 UTC, Suliman wrote:
> On Friday, 28 April 2017 at 15:45:25 UTC, Suliman wrote:
>> I am using https://github.com/mysql-d/mysql-native
>> It's return from DB variant data-type.
>>
>> My DB include value: 56.051151 (double type in DB)
>>
>> I need to extract it. I tried several variants:
>>
>> writeln(point[3].coerce!float);
>> writeln(point[3].coerce!string);
>> writeln(point[3].coerce!double);
>>
>> but all of them return me it as: 56.0512
>>
>> How to return exactly 56.051151 ?
>
> import std.stdio;
> import std.variant;
>
> void main()
> {
> 	Variant b = 56.051151;
> 	float x = b.coerce!float;
> 	writeln(x);
> }
>
>>56.0512

The precision is still there, you're just not requesting it:

import std.conv : text;
import std.stdio;
import std.variant;

void main()
{
    Variant b = 56.051151;
    float x = b.coerce!float;

    foreach (i; 0 .. 10)
        writefln(text("%.", i, "f"), x);
}

56
56.1
56.05
56.051
56.0512
56.05115
56.051151
56.0511513
56.05115128
56.051151276

> How to return exactly 56.051151 ?

Specify the number of digits after the decimal point manually, e.g. writefln("%.6f", x) will print 56.051151.
April 28, 2017
On Friday, 28 April 2017 at 16:24:55 UTC, Suliman wrote:
> import std.stdio;
> import std.variant;
>
> void main()
> {
> 	Variant b = 56.051151;
> 	float x = b.coerce!float;
> 	writeln(x);
> }
>
>>56.0512

void main()
{
    import core.stdc.stdio;
    import std.stdio;

    double d = 56.051151;
    writeln(d);
    printf("%g %f %a\n\n", d, d, d);

    real r = 56.051151L;
    writeln(r);
    printf("%Lg %Lf %La\n", r, r, r);
}

=>

56.0512
56.0512 56.051151 0x1.c068c1db0142fp+5

56.0512
56.0512 56.051151 0x1.c068c1db0142f61ep+5

So using write[ln]() to check floating-point values isn't a good idea as you may lose precision; hex formatting (or a proper debugger) is a much better choice. Additionally, your value isn't *exactly* representable; you may want to read up on floating-point representations if that's unclear.
April 28, 2017
On Friday, 28 April 2017 at 16:49:18 UTC, kinke wrote:
> On Friday, 28 April 2017 at 16:24:55 UTC, Suliman wrote:
>> import std.stdio;
>> import std.variant;
>>
>> void main()
>> {
>> 	Variant b = 56.051151;
>> 	float x = b.coerce!float;
>> 	writeln(x);
>> }
>>
>>>56.0512
>
> void main()
> {
>     import core.stdc.stdio;
>     import std.stdio;
>
>     double d = 56.051151;
>     writeln(d);
>     printf("%g %f %a\n\n", d, d, d);
>
>     real r = 56.051151L;
>     writeln(r);
>     printf("%Lg %Lf %La\n", r, r, r);
> }
>
> =>
>
> 56.0512
> 56.0512 56.051151 0x1.c068c1db0142fp+5
>
> 56.0512
> 56.0512 56.051151 0x1.c068c1db0142f61ep+5
>
> So using write[ln]() to check floating-point values isn't a good idea as you may lose precision; hex formatting (or a proper debugger) is a much better choice. Additionally, your value isn't *exactly* representable; you may want to read up on floating-point representations if that's unclear.

Yeah! It was issue with rounding during writeln
April 28, 2017
On Friday, 28 April 2017 at 16:42:28 UTC, Petar Kirov [ZombineDev] wrote:
> On Friday, 28 April 2017 at 16:24:55 UTC, Suliman wrote:
>> On Friday, 28 April 2017 at 15:45:25 UTC, Suliman wrote:
>>> I am using https://github.com/mysql-d/mysql-native
>>> It's return from DB variant data-type.
>>>
>>> My DB include value: 56.051151 (double type in DB)
>>>
>>> I need to extract it. I tried several variants:
>>>
>>> writeln(point[3].coerce!float);
>>> writeln(point[3].coerce!string);
>>> writeln(point[3].coerce!double);
>>>
>>> but all of them return me it as: 56.0512
>>>
>>> How to return exactly 56.051151 ?
>>
>> import std.stdio;
>> import std.variant;
>>
>> void main()
>> {
>> 	Variant b = 56.051151;
>> 	float x = b.coerce!float;
>> 	writeln(x);
>> }
>>
>>>56.0512
>
> The precision is still there, you're just not requesting it:
>
> import std.conv : text;
> import std.stdio;
> import std.variant;
>
> void main()
> {
>     Variant b = 56.051151;
>     float x = b.coerce!float;
>
>     foreach (i; 0 .. 10)
>         writefln(text("%.", i, "f"), x);
> }
>
> 56
> 56.1
> 56.05
> 56.051
> 56.0512
> 56.05115
> 56.051151
> 56.0511513
> 56.05115128
> 56.051151276
>
>> How to return exactly 56.051151 ?
>
> Specify the number of digits after the decimal point manually, e.g. writefln("%.6f", x) will print 56.051151.

BTW, you should always try to use the same floating-point type, so if you use 64-bit doubles in the database, you should also use double in your D code, otherwise you may accumulate rounding errors after each conversion. When converting to smaller floating-point types (real -> double and double -> float) you are essentially throwing out precision. For example:

import std.conv : text;
import std.stdio;
import std.variant;

void main()
{
    Variant b = 56.051151;

    foreach (i; 0 .. 16)
    {
        writefln(text("%.", i, "f"), b.coerce!float);
        writefln(text("%.", i, "f"), b.coerce!double);
    }
}

Notice how the floats and doubles differ at i >= 6.

56
56
56.1
56.1
56.05
56.05
56.051
56.051
56.0512
56.0512
56.05115
56.05115
56.051151
56.051151
56.0511513
56.0511510
56.05115128
56.05115100
56.051151276
56.051151000
56.0511512756
56.0511510000
56.05115127563
56.05115100000
56.051151275635
56.051151000000
56.0511512756348
56.0511510000000
56.05115127563477
56.05115100000000
56.051151275634766
56.051150999999997
April 28, 2017
On Fri, Apr 28, 2017 at 04:42:28PM +0000, via Digitalmars-d-learn wrote: [...]
>         writefln(text("%.", i, "f"), x);
[...]

There's no need to use text() here:

	writefln("%.*f", i, x);

does what you want.


T

-- 
"You know, maybe we don't *need* enemies." "Yeah, best friends are about all I can take." -- Calvin & Hobbes
April 29, 2017
On Friday, 28 April 2017 at 18:08:38 UTC, H. S. Teoh wrote:
> On Fri, Apr 28, 2017 at 04:42:28PM +0000, via Digitalmars-d-learn wrote: [...]
>>         writefln(text("%.", i, "f"), x);
> [...]
>
> There's no need to use text() here:
>
> 	writefln("%.*f", i, x);
>
> does what you want.
>
>
> T

Thanks, I missed the fact that * could be used for specifying the precision, in addition to the width.

May 02, 2017
On Saturday, 29 April 2017 at 08:57:09 UTC, Petar Kirov [ZombineDev] wrote:
> On Friday, 28 April 2017 at 18:08:38 UTC, H. S. Teoh wrote:
>> On Fri, Apr 28, 2017 at 04:42:28PM +0000, via Digitalmars-d-learn wrote: [...]
>>>         writefln(text("%.", i, "f"), x);
>> [...]
>>
>> There's no need to use text() here:
>>
>> 	writefln("%.*f", i, x);
>>
>> does what you want.
>>
>>
>> T
>
> Thanks, I missed the fact that * could be used for specifying the precision, in addition to the width.

I need co concatenate string with variant type (I am doing SQL query).

What is the best way to put it? It's seems that if I am doing simple `replace`

string sql = "..."
sql.replace(`37.72308`, to!string(cargpspoint.lon)).replace(`55.47957`, to!string(cargpspoint.lat))

I am loosing accuracy. Is there any better way?
May 02, 2017
On Tuesday, 2 May 2017 at 08:02:23 UTC, Suliman wrote:
> On Saturday, 29 April 2017 at 08:57:09 UTC, Petar Kirov [ZombineDev] wrote:
>> On Friday, 28 April 2017 at 18:08:38 UTC, H. S. Teoh wrote:
>>> On Fri, Apr 28, 2017 at 04:42:28PM +0000, via Digitalmars-d-learn wrote: [...]
>>>>         writefln(text("%.", i, "f"), x);
>>> [...]
>>>
>>> There's no need to use text() here:
>>>
>>> 	writefln("%.*f", i, x);
>>>
>>> does what you want.
>>>
>>>
>>> T
>>
>> Thanks, I missed the fact that * could be used for specifying the precision, in addition to the width.
>
> I need co concatenate string with variant type (I am doing SQL query).
>
> What is the best way to put it? It's seems that if I am doing simple `replace`
>
> string sql = "..."
> sql.replace(`37.72308`, to!string(cargpspoint.lon)).replace(`55.47957`, to!string(cargpspoint.lat))
>
> I am loosing accuracy. Is there any better way?

I did:
sql_distance.replace(`37.72308`, format("%f",cargpspoint.lon))

It's seems that it's work ok. But is there any better way, or it's ok?
« First   ‹ Prev
1 2