Thread overview
string to real conversion losing data
Apr 08, 2010
jicman
Apr 08, 2010
wrzosk
Apr 09, 2010
jicman
Apr 08, 2010
bearophile
Apr 08, 2010
BCS
Apr 09, 2010
Ali Çehreli
Apr 09, 2010
Ali Çehreli
Apr 10, 2010
jicman
April 08, 2010
Greetings and salutations!

Will someone be so kind as to explain why this is happening?

----
import std.stdio;
import std.conv;

void main()
{
  char[][] strRealVals =
  [
    "14539.34","1230.00","361.62","1613.10","","","0.00"
  ];
  real rTotal = 0;
  foreach (char[] s; strRealVals)
  {
    writefln("Real value is: " ~ s);
    real r = 0.00;
    if (s != "")
      r = std.conv.toReal(s);
    rTotal += r;
  }
  writefln(std.string.toString(rTotal));
  writefln(rTotal);
}
----

When I run this program, I get this:
16:51:35.54>realtest
Real value is: 14539.34
Real value is: 1230.00
Real value is: 361.62
Real value is: 1613.10
Real value is:
Real value is:
Real value is: 0.00
17744.1
17744.1

----

If I add these numbers, the outcome should be 17744.06.  Any ideas?  I am using Digital Mars D Compiler v1.046.

thanks,

josé

April 08, 2010
W dniu 08.04.2010 23:02, jicman pisze:
>
> Greetings and salutations!
>
> Will someone be so kind as to explain why this is happening?
>
> ----
> import std.stdio;
> import std.conv;
>
> void main()
> {
>    char[][] strRealVals =
>    [
>      "14539.34","1230.00","361.62","1613.10","","","0.00"
>    ];
>    real rTotal = 0;
>    foreach (char[] s; strRealVals)
>    {
>      writefln("Real value is: " ~ s);
>      real r = 0.00;
>      if (s != "")
>        r = std.conv.toReal(s);
>      rTotal += r;
>    }
>    writefln(std.string.toString(rTotal));
>    writefln(rTotal);
> }
> ----
>
> When I run this program, I get this:
> 16:51:35.54>realtest
> Real value is: 14539.34
> Real value is: 1230.00
> Real value is: 361.62
> Real value is: 1613.10
> Real value is:
> Real value is:
> Real value is: 0.00
> 17744.1
> 17744.1
>
> ----
>
> If I add these numbers, the outcome should be 17744.06.  Any ideas?  I am using Digital Mars D Compiler v1.046.
>
> thanks,
>
> jos�
>

it is looking ok to me, try this one and thing why it is like that :)


import std.stdio;
import std.conv;

void main()
{
	writefln(17744.06);
}
April 08, 2010
> If I add these numbers, the outcome should be 17744.06.  Any ideas?  I am using Digital Mars D Compiler v1.046. josé

This prints the same values, using latest D2:


import std.stdio, std.conv;

void main() {
    real tot = 0;
    foreach(el; ["14539.34","1230.00","361.62","1613.10","0.00"])
        tot += to!real(el);
    writefln("%.5f\n", tot); // 17744.06000

    tot = 0;
    foreach(el; [14539.34,1230.00,361.62,1613.10,0.00])
        tot += to!real(el);
    writefln("%.5f\n", tot); // 17744.06000
}

Bye,
bearophile
April 08, 2010
Hello bearophile,

> writefln("%.5f\n", tot); // 17744.06000

Never trust your output function :) (e.i. always check to see if it's doing what you think it is.)

Back in the bad old days, a guy I knew spent a while debugging a problem that turned out to be that he was loading data as float but storing it into an int (think an invalid scanf format string). Every time he checked things though things seems OK because he had the same bug in his output as well (think printf).

-- 
... <IXOYE><



April 09, 2010
wrzosk Wrote:

> W dniu 08.04.2010 23:02, jicman pisze:
> >
> 
> it is looking ok to me, try this one and thing why it is like that :)
> 
> 
> import std.stdio;
> import std.conv;
> 
> void main()
> {
> 	writefln(17744.06);
> }

Ok, I'll bite... I don't get it.  does that mean that writefln is buggy?  How can I format and write this to a file?  Is there a formatting library?

thanks,

jose

April 09, 2010
jicman wrote:
> Greetings and salutations!
> 
> Will someone be so kind as to explain why this is happening?
> 
> ----
> import std.stdio;
> import std.conv;
> 
> void main()
> {
>   char[][] strRealVals =
>   [
>     "14539.34","1230.00","361.62","1613.10","","","0.00"
>   ];
>   real rTotal = 0;
>   foreach (char[] s; strRealVals)
>   {
>     writefln("Real value is: " ~ s);
>     real r = 0.00;
>     if (s != "")
>       r = std.conv.toReal(s);
>     rTotal += r;
>   }
>   writefln(std.string.toString(rTotal));
>   writefln(rTotal);
> }
> ----
> 
> When I run this program, I get this:
> 16:51:35.54>realtest
> Real value is: 14539.34
> Real value is: 1230.00
> Real value is: 361.62
> Real value is: 1613.10
> Real value is:
> Real value is:
> Real value is: 0.00
> 17744.1
> 17744.1
> 
> ----
> 
> If I add these numbers, the outcome should be 17744.06.  Any ideas?  I am using Digital Mars D Compiler v1.046.
> 
> thanks,
> 
> jos�
> 

The default format string for floating point values is 6 decimal digits of precision (the digits before and after the decimal point). writefln is rounding the value up.

Try for example "%.18f" for 'real'. This does it automatically:

import std.stdio;
import std.string;

void main()
{
    auto theValue = 17744.06L;

    writefln("%s has %s decimal digits of precision",
             typeof(theValue).stringof, theValue.dig);

    auto formatString = format("%%.%sf", theValue.dig);
    writefln(formatString, theValue);
}

Ali
April 09, 2010
Ali Çehreli wrote:

> Try for example "%.18f" for 'real'.

Well... That will be too many digits unless the number of digits before the decimal point is zero.

The decimal digits before and after the point should be 18 for most accurate representation. But the OP probably doesn't need that many digits anyway.

Here are more options:

  http://digitalmars.com/d/2.0/phobos/std_format.html

Ali
April 10, 2010
Ali Çehreli Wrote:

> jicman wrote:
> > Greetings and salutations!
> > 
> > Will someone be so kind as to explain why this is happening?
> > 
> > ----
> > import std.stdio;
> > import std.conv;
> > 
> > void main()
> > {
> >   char[][] strRealVals =
> >   [
> >     "14539.34","1230.00","361.62","1613.10","","","0.00"
> >   ];
> >   real rTotal = 0;
> >   foreach (char[] s; strRealVals)
> >   {
> >     writefln("Real value is: " ~ s);
> >     real r = 0.00;
> >     if (s != "")
> >       r = std.conv.toReal(s);
> >     rTotal += r;
> >   }
> >   writefln(std.string.toString(rTotal));
> >   writefln(rTotal);
> > }
> > ----
> > 
> > When I run this program, I get this:
> > 16:51:35.54>realtest
> > Real value is: 14539.34
> > Real value is: 1230.00
> > Real value is: 361.62
> > Real value is: 1613.10
> > Real value is:
> > Real value is:
> > Real value is: 0.00
> > 17744.1
> > 17744.1
> > 
> > ----
> > 
> > If I add these numbers, the outcome should be 17744.06.  Any ideas?  I am using Digital Mars D Compiler v1.046.
> > 
> > thanks,
> > 
> > jos�
> > 
> 
> The default format string for floating point values is 6 decimal digits of precision (the digits before and after the decimal point). writefln is rounding the value up.
> 
> Try for example "%.18f" for 'real'. This does it automatically:
> 
> import std.stdio;
> import std.string;
> 
> void main()
> {
>      auto theValue = 17744.06L;
> 
>      writefln("%s has %s decimal digits of precision",
>               typeof(theValue).stringof, theValue.dig);
> 
>      auto formatString = format("%%.%sf", theValue.dig);
>      writefln(formatString, theValue);
> }
> 

thanks.  That worked.

jic