Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 03, 2017 Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to Saurabh Das | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to Saurabh Das | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | 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 Re: Funny issue with casting double to ulong | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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.
|
Copyright © 1999-2021 by the D Language Foundation