## digitalmars.D.learn - Funny issue with casting double to ulong

• Saurabh Das (24/24) Jul 02 2017 Consider this snippet:
• Basile B (8/32) Jul 02 2017 6.251 has no perfect double representation. It's real value is:
Saurabh Das <saurabh.das gmail.com> writes:
```Consider this snippet:

void main()
{
import std.stdio;
auto a = 6.2151;
auto b = a * 10000;
auto c = cast(ulong)b;
writeln("a: ", typeof(a).stringof, " ", a);
writeln("b: ", typeof(b).stringof, " ", b);
writeln("c: ", typeof(c).stringof, " ", c);

auto x = 62151.0;
auto y = cast(ulong)x;
writeln("x: ", typeof(x).stringof, " ", x);
writeln("y: ", typeof(y).stringof, " ", y);
}

The output is:
a: double 6.2151
b: double 62151
c: ulong 62150
x: double 62151
y: ulong 62151

Why does c round off from 62151 to 62150 when casting to ulong?

Thanks,
Saurabh
```
Jul 02 2017
Basile B <b2.temp gmx.com> writes:
```On Monday, 3 July 2017 at 03:50:14 UTC, Saurabh Das wrote:
Consider this snippet:

void main()
{
import std.stdio;
auto a = 6.2151;
auto b = a * 10000;
auto c = cast(ulong)b;
writeln("a: ", typeof(a).stringof, " ", a);
writeln("b: ", typeof(b).stringof, " ", b);
writeln("c: ", typeof(c).stringof, " ", c);

auto x = 62151.0;
auto y = cast(ulong)x;
writeln("x: ", typeof(x).stringof, " ", x);
writeln("y: ", typeof(y).stringof, " ", y);
}

The output is:
a: double 6.2151
b: double 62151
c: ulong 62150
x: double 62151
y: ulong 62151

Why does c round off from 62151 to 62150 when casting to ulong?

Thanks,
Saurabh

6.251 has no perfect double representation. It's real value is:

6.21509999999999962483343551867E0

Hence when you cast to ulong after the product by 10_000, this is
the equivalent of

trunc(62150.9999999999962483343551867E0)

which gives 62150

CQFD ;-]
```
Jul 02 2017
Saurabh Das <saurabh.das gmail.com> writes:
```On Monday, 3 July 2017 at 03:57:25 UTC, Basile B wrote:
On Monday, 3 July 2017 at 03:50:14 UTC, Saurabh Das wrote:
[...]

6.251 has no perfect double representation. It's real value is:

6.21509999999999962483343551867E0

Hence when you cast to ulong after the product by 10_000, this
is the equivalent of

trunc(62150.9999999999962483343551867E0)

which gives 62150

CQFD ;-]

That explains it!

Thank you.
```
Jul 02 2017
Basile dlang-community <b2.temp gmx.com> writes:
```On Monday, 3 July 2017 at 04:06:23 UTC, Saurabh Das wrote:
On Monday, 3 July 2017 at 03:57:25 UTC, Basile B wrote:
On Monday, 3 July 2017 at 03:50:14 UTC, Saurabh Das wrote:
[...]

6.251 has no perfect double representation. It's real value is:

6.21509999999999962483343551867E0

Hence when you cast to ulong after the product by 10_000, this
is the equivalent of

trunc(62150.9999999999962483343551867E0)

which gives 62150

CQFD ;-]

That explains it!

Thank you.

There's been a small typo in my answer. "6.251" i meant obviously
"6.2151".
Anyway it doesn't change anything the most accurate double
representation is well
the long number i said.
```
Jul 03 2017
Era Scarecrow <rtcvb32 yahoo.com> writes:
```On Monday, 3 July 2017 at 03:57:25 UTC, Basile B wrote:
6.251 has no perfect double representation. It's real value is:

I almost wonder if a BCD, fixed length or alternative for
floating point should be an option... Either library, or a hook
to change how the FPU works since doubles are suppose to do 16-18
digits of perfect simple floatingpoint for the purposes of money
and the like without relying on such imperfect transitions.
```
Jul 02 2017
"H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
```On Mon, Jul 03, 2017 at 05:38:56AM +0000, Era Scarecrow via Digitalmars-d-learn
wrote:
On Monday, 3 July 2017 at 03:57:25 UTC, Basile B wrote:
6.251 has no perfect double representation. It's real value is:

I almost wonder if a BCD, fixed length or alternative for floating
point should be an option... Either library, or a hook to change how
the FPU works since doubles are suppose to do 16-18 digits of perfect
simple floatingpoint for the purposes of money and the like without
relying on such imperfect transitions.

From what I've heard, word on the street is to avoid using

floating-point for money calculations, and use fixed-point arithmetic
instead (i.e., basically ints / longs, with a built-in decimal point in
a fixed position).  Inexact representations of certain fractions of tens
like the above are one reason for this.

I don't think there's a way to change how the FPU works -- the hardware
is coded that way and can't be changed.  You'd have to build your own
library or use an existing one for this purpose.

T

--
Food and laptops don't mix.
```
Jul 02 2017
Era Scarecrow <rtcvb32 yahoo.com> writes:
```On Monday, 3 July 2017 at 06:20:22 UTC, H. S. Teoh wrote:
On Mon, Jul 03, 2017 at 05:38:56AM +0000, Era Scarecrow via
Digitalmars-d-learn wrote:
I almost wonder if a BCD, fixed length or alternative for
floating point should be an option...

From what I've heard, word on the street is to avoid using
floating-point for money calculations, and use fixed-point
arithmetic instead (I.e., basically ints / longs, with a
built-in decimal point in a fixed position).  Inexact
representations of certain fractions of tens like the above are
one reason for this.

I don't think there's a way to change how the FPU works -- the
hardware is coded that way and can't be changed.  You'd have to
build your own library or use an existing one for this purpose.

It's been a while, i do recall there was BCD options, actually
found a few of the instructions; However they are more on
loading/storing the value, not on working strictly in that mode.
Last i remember seeing references to BCD work was in 2000 or so.

I'll have to look further before i find (or fail to find) all
that's BCD related. Still if it IS avaliable, it would be an x87
only option and thus wouldn't be portable unless the language or
a library offered support.
```
Jul 03 2017
"H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
```On Mon, Jul 03, 2017 at 07:13:45AM +0000, Era Scarecrow via Digitalmars-d-learn
wrote:
On Monday, 3 July 2017 at 06:20:22 UTC, H. S. Teoh wrote:

[...]
I don't think there's a way to change how the FPU works -- the
hardware is coded that way and can't be changed.  You'd have to
build your own library or use an existing one for this purpose.

It's been a while, i do recall there was BCD options, actually found
a few of the instructions; However they are more on loading/storing
the value, not on working strictly in that mode. Last i remember
seeing references to BCD work was in 2000 or so.

I'll have to look further before i find (or fail to find) all that's
BCD related. Still if it IS avaliable, it would be an x87 only option
and thus wouldn't be portable unless the language or a library offered
support.

Wow, that brings back the memories... I used to dabble with BCD (only a
little bit) back when I was playing with 8086/8088 assembly language.
But I've not heard anything about BCD since that era, and I'm surprised
people still know what it is. :-D  But all I knew about BCD was in the
realm of integer arithmetic. I had no idea such things as BCD floats
existed.

T

--
An imaginary friend squared is a real enemy.
```
Jul 03 2017
Patrick Schluter <Patrick.Schluter bbox.fr> writes:
```On Tuesday, 4 July 2017 at 00:35:10 UTC, H. S. Teoh wrote:
On Mon, Jul 03, 2017 at 07:13:45AM +0000, Era Scarecrow via
Digitalmars-d-learn wrote:
On Monday, 3 July 2017 at 06:20:22 UTC, H. S. Teoh wrote:

[...]
I don't think there's a way to change how the FPU works --
the hardware is coded that way and can't be changed.  You'd
have to build your own library or use an existing one for
this purpose.

It's been a while, i do recall there was BCD options,
actually found
a few of the instructions; However they are more on
loading/storing
the value, not on working strictly in that mode. Last i
remember
seeing references to BCD work was in 2000 or so.

I'll have to look further before i find (or fail to find) all
that's
BCD related. Still if it IS avaliable, it would be an x87 only
option
and thus wouldn't be portable unless the language or a library
offered
support.

Wow, that brings back the memories... I used to dabble with BCD
(only a little bit) back when I was playing with 8086/8088
assembly language. But I've not heard anything about BCD since
that era, and I'm surprised people still know what it is. :-D
But all I knew about BCD was in the realm of integer
arithmetic. I had no idea such things as BCD floats existed.

In times of lore, BCD floats were very common. The Sharp Pocket
Computer used a BCD float format and writing machine code on them
confronts one with the format. The TI-99/4A home computer also
used a BCD float format in its Basic interpreter. It had the same
properties as the float format of the TI calculators, i.e. 10
visible significant digits (+ 3 hidden digits) and exponents
going from -99 to +99. It is only then when I switched to the
Apple II Applesoft Basic that I discovered the horrors of binary
floating point numbers.
Since the generalization of arithmetic co-processors does one
only see binary floats anymore.
```
Jul 04 2017
Era Scarecrow <rtcvb32 yahoo.com> writes:
```On Tuesday, 4 July 2017 at 12:32:26 UTC, Patrick Schluter wrote:
In times of lore, BCD floats were very common. The Sharp Pocket
Computer used a BCD float format and writing machine code on
them confronts one with the format. The TI-99/4A home computer
also used a BCD float format in its Basic interpreter. It had
the same properties as the float format of the TI calculators,
I.e. 10 visible significant digits (+ 3 hidden digits) and
exponents going from -99 to +99.

If you look at the instruction set for 6502 (and probably similar
4-8bit CPU's) they literally don't deal with anything other than
8bit add/subtraction & other basic binary operators. Without
multiplication or division all of that has to be simulated in
software. And only needing 10 instructions to do just about
everything, well...

BCD of course has a big advantage built-in: Because it's all
base10, converting BCD to a string and printing it is very fast
(as well as precise). And with 1 byte reserved for exponent,
raising/lowering the level is also very very easy and goes a very
large range.

There's also a series of algorithms for calculating some of the
more complex functions using small tables or an iteration of
shift & add which is implemented on calculators allowing a
simpler (and reduced) instruction set or fewer transistors to
make calculators work (CORDIC). It's actually pretty fascinating
to read about.

BCD could still be an option though... I could probably write
one; Although with doubles avaliable, you probably don't need it.
```
Jul 04 2017
Patrick Schluter <Patrick.Schluter bbox.fr> writes:
```On Monday, 3 July 2017 at 05:38:56 UTC, Era Scarecrow wrote:
On Monday, 3 July 2017 at 03:57:25 UTC, Basile B wrote:
6.251 has no perfect double representation. It's real value is:

I almost wonder if a BCD, fixed length or alternative for
floating point should be an option... Either library, or a hook
to change how the FPU works since doubles are suppose to do
16-18 digits of perfect simple floatingpoint for the purposes
of money and the like without relying on such imperfect
transitions.

IBM zSeries and POWER since POWER6 have BCD floating point unit...
```
Jul 03 2017