Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 28, 2017 problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to Suliman | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to Suliman | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to Suliman | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to kinke | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to Petar Kirov [ZombineDev] | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to Petar Kirov [ZombineDev] | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to Petar Kirov [ZombineDev] | 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 Re: problem with std.variant rounding | ||||
---|---|---|---|---|
| ||||
Posted in reply to Suliman | 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? |
Copyright © 1999-2021 by the D Language Foundation