digitalmars.D.learn - problem with std.variant rounding
- Suliman (9/9) Apr 28 2017 I am using https://github.com/mysql-d/mysql-native
- Suliman (9/19) Apr 28 2017 import std.stdio;
- Petar Kirov [ZombineDev] (24/49) Apr 28 2017 The precision is still there, you're just not requesting it:
- Petar Kirov [ZombineDev] (53/105) Apr 28 2017 BTW, you should always try to use the same floating-point type,
- H. S. Teoh via Digitalmars-d-learn (9/10) Apr 28 2017 [...]
- Petar Kirov [ZombineDev] (3/11) Apr 29 2017 Thanks, I missed the fact that * could be used for specifying the
- Suliman (11/27) May 02 2017 I need co concatenate string with variant type (I am doing SQL
- Suliman (5/33) May 02 2017 I did:
- Nick Sabalausky (Abscissa) (21/28) May 02 2017 Building SQL strings manually isn't really good practice these days, for...
- kinke (22/31) Apr 28 2017 void main()
- Suliman (2/35) Apr 28 2017 Yeah! It was issue with rounding during writeln
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 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
Apr 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: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.051151276I 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.0512How 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 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: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.051150999999997On Friday, 28 April 2017 at 15:45:25 UTC, Suliman wrote: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.051151276I 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.0512How 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 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
Apr 28 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: [...]Thanks, I missed the fact that * could be used for specifying the precision, in addition to the width.writefln(text("%.", i, "f"), x);[...] There's no need to use text() here: writefln("%.*f", i, x); does what you want. T
Apr 29 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: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?On Fri, Apr 28, 2017 at 04:42:28PM +0000, via Digitalmars-d-learn wrote: [...]Thanks, I missed the fact that * could be used for specifying the precision, in addition to the width.writefln(text("%.", i, "f"), x);[...] There's no need to use text() here: writefln("%.*f", i, x); does what you want. T
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: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?On Friday, 28 April 2017 at 18:08:38 UTC, H. S. Teoh 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?On Fri, Apr 28, 2017 at 04:42:28PM +0000, via Digitalmars-d-learn wrote: [...]Thanks, I missed the fact that * could be used for specifying the precision, in addition to the width.writefln(text("%.", i, "f"), x);[...] There's no need to use text() here: writefln("%.*f", i, x); does what you want. T
May 02 2017
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 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); }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.56.0512
Apr 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:Yeah! It was issue with rounding during writelnimport std.stdio; import std.variant; void main() { Variant b = 56.051151; float x = b.coerce!float; writeln(x); }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.56.0512
Apr 28 2017