www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Stop to! rounding?

reply "Josh" <moonburntm gmail.com> writes:
writeln(to!double("151.42499"));    //prints 151.425

Is there any way to stop this rounding?

Thanks,
Josh
Jul 02 2013
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, July 03, 2013 06:23:12 Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425
 
 Is there any way to stop this rounding?
No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
Jul 02 2013
next sibling parent reply "Josh" <moonburntm gmail.com> writes:
On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote:
 On Wednesday, July 03, 2013 06:23:12 Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425
 
 Is there any way to stop this rounding?
No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
Is there any way I would be able to hold that number then? Thanks, Josh
Jul 02 2013
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, July 03, 2013 06:44:33 Josh wrote:
 On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote:
 On Wednesday, July 03, 2013 06:23:12 Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425
 
 Is there any way to stop this rounding?
No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
Is there any way I would be able to hold that number then?
Without rounding? You'd need fixed point math rather than floating point math. There is nothing built into the language to support that (or into any C-based language of which I'm aware). I believe that C libraries exist which provide it though. http://en.wikipedia.org/wiki/Fixed-point_arithmetic Most people just use floating point though, since in most cases, you really don't need fixed point. - Jonathan M Davis
Jul 02 2013
parent reply "Josh" <moonburntm gmail.com> writes:
On Wednesday, 3 July 2013 at 04:51:06 UTC, Jonathan M Davis wrote:
 On Wednesday, July 03, 2013 06:44:33 Josh wrote:
 On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis 
 wrote:
 On Wednesday, July 03, 2013 06:23:12 Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425
 
 Is there any way to stop this rounding?
No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
Is there any way I would be able to hold that number then?
Without rounding? You'd need fixed point math rather than floating point math. There is nothing built into the language to support that (or into any C-based language of which I'm aware). I believe that C libraries exist which provide it though. http://en.wikipedia.org/wiki/Fixed-point_arithmetic Most people just use floating point though, since in most cases, you really don't need fixed point. - Jonathan M Davis
Jonathan, do you know of any fixed point D library? If not, would it be worth me making one for phobos? Thanks, Josh
Jul 02 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, July 03, 2013 08:11:50 Josh wrote:
 Jonathan, do you know of any fixed point D library? If not, would
 it be worth me making one for phobos?
I am unaware of one, and I don't really know why anyone would really want fixed point rather than floating point, so I don't know what use cases it would be valid for or how much interest there would really be in adding something like that to Phobos. However, there's probably a decent chance of something like that making it into Phobos if someone came up with a solid implemantation for it. - Jonathan M Davis
Jul 02 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 3 July 2013 at 06:18:28 UTC, Jonathan M Davis wrote:
 On Wednesday, July 03, 2013 08:11:50 Josh wrote:
 Jonathan, do you know of any fixed point D library? If not, 
 would
 it be worth me making one for phobos?
I am unaware of one, and I don't really know why anyone would really want fixed point rather than floating point, so I don't know what use cases it would be valid for or how much interest there would really be in adding something like that to Phobos. - Jonathan M Davis
Said the man who then went on to state "I really don't like dealing with floating point numbers." ;) That said, fixed point types, and/or "decimal floating point types" are both very important features to specific domains: Just the same way certain fields (gaming) have weird requirements, so do certain other fields. My brother in law writes financial apps, and in that field, using floating points type is *legally* forbidden. My wife writes the embeded code for a machine here company manufactures. Ditto: no floating point types allowed. She's told me that their code is *riddled* with things like "mv = v * 1000": because they don't have a way to handle fractinal numbers. Long story short, I think both would be a great addition to phobos/D. I'd personally really want to play with decimal floats: They are slower, less precise and have less range, but are more "exact" in base 10 than traditional floats. And when printed in Base 10, are *always* exact.
Jul 03 2013
next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Wednesday, 3 July 2013 at 08:23:40 UTC, monarch_dodra wrote:
 My brother in law writes financial apps, and in that field, 
 using floating points type is *legally* forbidden.
Really? What kind of apps?
Jul 03 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 3 July 2013 at 08:27:52 UTC, Maxim Fomin wrote:
 On Wednesday, 3 July 2013 at 08:23:40 UTC, monarch_dodra wrote:
 My brother in law writes financial apps, and in that field, 
 using floating points type is *legally* forbidden.
Really? What kind of apps?
I meant "apps" as in short for program, not phone "apps". It's complicated to explain, but in a word, He basically programs distributed servers to do stock trading. I'm not allowed to talk about it much, especially on some random board :( About the whole "legally forbidden" thing: I'm not sure it is the entire "financial" field, but definitly in the accounting field.
Jul 03 2013
prev sibling parent "Jay Norwood" <jayn prismnet.com> writes:
On Wednesday, 3 July 2013 at 08:23:40 UTC, monarch_dodra wrote:
 On Wednesday, 3 July 2013 at 06:18:28 UTC, Jonathan M Davis 
 wrote:
 On Wednesday, July 03, 2013 08:11:50 Josh wrote:
 Long story short, I think both would be a great addition to 
 phobos/D. I'd personally really want to play with decimal 
 floats: They are slower, less precise and have less range, but 
 are more "exact" in base 10 than traditional floats. And when 
 printed in Base 10, are *always* exact.
This arbitrary precision c++ arithmetic package has a flexible feature of allowing selection of the internal base. The default base 10. Much of it is implemented in c++ templates. I put a small excerpt below. http://www.hvks.com/Numerical/arbitrary_precision.html /// Description: /// Add operator for float_precision + <any other type> /// no const on the lhs parameter to prevent ambigous overload /// template <class _Ty> inline float_precision operator+( float_precision& lhs, const _Ty& rhs ) { float_precision c(rhs); if( lhs.precision() > c.precision() ) c.precision( lhs.precision() ); return c += lhs; }
Jul 03 2013
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Josh:

 Is there any way I would be able to hold that number then?
One way to do that is with a simple rationals library, represented as pairs of bigints. Bye, bearophile
Jul 03 2013
prev sibling parent reply "cal" <callumenator gmail.com> writes:
On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote:
 On Wednesday, July 03, 2013 06:23:12 Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425
 
 Is there any way to stop this rounding?
No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
void main() { double d = 151.42499; assert(d == 151.42499); } The rounding occurs in writeln surely.
Jul 02 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, July 03, 2013 07:04:47 cal wrote:
 On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote:
 On Wednesday, July 03, 2013 06:23:12 Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425
 
 Is there any way to stop this rounding?
No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
void main() { double d = 151.42499; assert(d == 151.42499); } The rounding occurs in writeln surely.
That's true because _both_ of the floating point values there get rounded to 151.425, and 151.425 is equal to 151.425. writeln is not doing anything wrong. I highly suggest that you read this: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html - Jonathan M Davis
Jul 02 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/02/2013 10:09 PM, Jonathan M Davis wrote:

 On Wednesday, July 03, 2013 07:04:47 cal wrote:
 void main()
 {
      double d = 151.42499;
      assert(d == 151.42499);
 }

 The rounding occurs in writeln surely.
That's true because _both_ of the floating point values there get
rounded to
 151.425,
The value that can be stored is not 151.42499, nor 151.425. import std.stdio; import std.conv; void main() { auto a = to!double("151.42499"); writefln("%.60f", a); } Prints: 151.424990000000008194547262974083423614501953125000000000000000
 writeln is not doing anything wrong.
True. It is using its default floating point precision, 6. Ali
Jul 02 2013
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jul 02, 2013 at 10:14:33PM -0700, Ali Çehreli wrote:
[...]
 import std.stdio;
 import std.conv;
 
 void main()
 {
     auto a = to!double("151.42499");
     writefln("%.60f", a);
 }
I wouldn't write it like that; IMO it's better to write: writefln("%.*f", double.dig, a); So that you don't give the wrong impression that there are more digits than are actually there. Using double.dig also lets you see all the digits that *are* there, not a rounded value, that the OP was complaining about. T -- The easy way is the wrong way, and the hard way is the stupid way. Pick one.
Jul 02 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/03/2013 07:21 AM, H. S. Teoh wrote:
 On Tue, Jul 02, 2013 at 10:14:33PM -0700, Ali Çehreli wrote:
 [...]
 import std.stdio;
 import std.conv;

 void main()
 {
      auto a = to!double("151.42499");
      writefln("%.60f", a);
 }
I wouldn't write it like that; IMO it's better to write: writefln("%.*f", double.dig, a); So that you don't give the wrong impression that there are more digits than are actually there. Using double.dig also lets you see all the digits that *are* there, not a rounded value, that the OP was complaining about. ...
double.dig gets you the number of significant digits in total. The number of significant digits after the decimal point is dependent on the exponent.
Jul 02 2013
prev sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Tue, 2 Jul 2013 22:21:52 -0700
schrieb "H. S. Teoh" <hsteoh quickfur.ath.cx>:

 On Tue, Jul 02, 2013 at 10:14:33PM -0700, Ali =C3=87ehreli wrote:
 [...]
 import std.stdio;
 import std.conv;
=20
 void main()
 {
     auto a =3D to!double("151.42499");
     writefln("%.60f", a);
 }
=20 I wouldn't write it like that; IMO it's better to write: =20 writefln("%.*f", double.dig, a); =20 So that you don't give the wrong impression that there are more digits than are actually there. Using double.dig also lets you see all the digits that *are* there, not a rounded value, that the OP was complaining about. =20 =20 T =20
*f ? I didn't know that you can format the format string like that. Thanks for the tip. --=20 Marco
Jul 03 2013
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Jul 03, 2013 at 07:56:28PM +0200, Marco Leise wrote:
 Am Tue, 2 Jul 2013 22:21:52 -0700
 schrieb "H. S. Teoh" <hsteoh quickfur.ath.cx>:
 
 On Tue, Jul 02, 2013 at 10:14:33PM -0700, Ali Çehreli wrote:
 [...]
 import std.stdio;
 import std.conv;
 
 void main()
 {
     auto a = to!double("151.42499");
     writefln("%.60f", a);
 }
I wouldn't write it like that; IMO it's better to write: writefln("%.*f", double.dig, a); So that you don't give the wrong impression that there are more digits than are actually there. Using double.dig also lets you see all the digits that *are* there, not a rounded value, that the OP was complaining about. T
*f ? I didn't know that you can format the format string like that. Thanks for the tip.
[...] Basically, it's a wildcard precision. Usually you'd write %.5f for 5 digits following the decimal point, for example, but that requires hardcoding the integer literal into the format string. In some cases you need it to be variable, so '*' was introduced as a stand-in for the next item in the argument list. So writefln("%.*f", 5, a) is equivalent to writefln("%.5f", a). The wildcard * can also be used in the field-width, so writefln("%*.*f", 5, 2, 1) is equivalent to writefln("%5.2f", 1). This isn't D's innovation, BTW, the * width/precision specifier is defined in the same way in C's printf(). T -- He who does not appreciate the beauty of language is not worthy to bemoan its flaws.
Jul 03 2013
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, July 02, 2013 22:14:33 Ali =C3=87ehreli wrote:
 On 07/02/2013 10:09 PM, Jonathan M Davis wrote:
  > On Wednesday, July 03, 2013 07:04:47 cal wrote:
  >> void main()
  >> {
  >>=20
  >>      double d =3D 151.42499;
  >>      assert(d =3D=3D 151.42499);
  >>=20
  >> }
  >>=20
  >> The rounding occurs in writeln surely.
  >=20
  > That's true because _both_ of the floating point values there get
=20
 rounded to
=20
  > 151.425,
=20
 The value that can be stored is not 151.42499, nor 151.425.
=20
 import std.stdio;
 import std.conv;
=20
 void main()
 {
      auto a =3D to!double("151.42499");
      writefln("%.60f", a);
 }
=20
 Prints:
=20
 151.424990000000008194547262974083423614501953125000000000000000
=20
  > writeln is not doing anything wrong.
=20
 True. It is using its default floating point precision, 6.
Ah. You learn new things every day. Well, I stand corrected. I was half= right.=20 It isn't 151.42499, but writeln _is_ rounding. I really don't like deal= ing=20 with floating point numbers. - Jonathan M Davis
Jul 02 2013
prev sibling parent "cal" <callumenator gmail.com> writes:
On Wednesday, 3 July 2013 at 05:10:03 UTC, Jonathan M Davis wrote:
 On Wednesday, July 03, 2013 07:04:47 cal wrote:
 On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis 
 wrote:
 On Wednesday, July 03, 2013 06:23:12 Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425
 
 Is there any way to stop this rounding?
No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
void main() { double d = 151.42499; assert(d == 151.42499); } The rounding occurs in writeln surely.
That's true because _both_ of the floating point values there get rounded to 151.425, and 151.425 is equal to 151.425. writeln is not doing anything wrong. I highly suggest that you read this: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html - Jonathan M Davis
import std.stdio; void main() { double d = 151.42499; writefln("%.10f", d); }
Jul 02 2013
prev sibling parent "cal" <callumenator gmail.com> writes:
On Wednesday, 3 July 2013 at 04:23:17 UTC, Josh wrote:
 writeln(to!double("151.42499"));    //prints 151.425

 Is there any way to stop this rounding?

 Thanks,
 Josh
The rounding is probably just a stdio default floating point format, ie: writefln("%.10f", to!double("151.42499")); // 151.4249900000
Jul 02 2013