www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - problem with std.variant rounding

reply Suliman <evermind live.ru> writes:
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 ?
Apr 28
parent reply Suliman <evermind live.ru> writes:
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
Apr 28
next sibling parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
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.
Apr 28
next sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
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
Apr 28
prev sibling parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
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
Apr 28
parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
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.
Apr 29
parent reply Suliman <evermind live.ru> writes:
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
next sibling parent Suliman <evermind live.ru> writes:
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?
May 02
prev sibling parent "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 05/02/2017 04:02 AM, Suliman wrote:
 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?
Building SQL strings manually isn't really good practice these days, for both that and other reasons. It's better to use prepared statements, which will fix that issue for you and will also ensure your code is not susceptible to SQL-injection attacks: // Raw SQL strings (old, ugly, unsafe way): auto name = "Fred"; auto num = 1.23; auto sql = text( "INSERT INTO `myTable` (`field1`, `field2`) VALUES ('", mysqlEscape(name), "', ", num, ")" ); exec(conn, sql); // Prepared statement (good, modern, safe way): auto name = "Fred"; auto num = 1.23; Prepared insertSomeFields = prepare(conn, "INSERT INTO `myTable` (`field1`, `field2`) VALUES (?, ?)" ); insertSomeFields.setArgs(name, num); insertSomeFields.exec();
May 02
prev sibling parent reply kinke <noone nowhere.com> writes:
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.
Apr 28
parent Suliman <evermind live.ru> writes:
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
Apr 28