Jump to page: 1 2
Thread overview
Funny issue with casting double to ulong
Jul 03, 2017
Saurabh Das
Jul 03, 2017
Basile B
Jul 03, 2017
Saurabh Das
Jul 03, 2017
Era Scarecrow
Jul 03, 2017
H. S. Teoh
Jul 03, 2017
Era Scarecrow
Jul 04, 2017
H. S. Teoh
Jul 04, 2017
Patrick Schluter
Jul 04, 2017
Era Scarecrow
Jul 03, 2017
Patrick Schluter
July 03, 2017
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

July 03, 2017
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 ;-]
July 03, 2017
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.
July 03, 2017
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.
July 02, 2017
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.
July 03, 2017
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.
July 03, 2017
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.
July 03, 2017
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...
July 03, 2017
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.
July 04, 2017
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.


« First   ‹ Prev
1 2