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 (3/12) Jul 02 2017 That explains it!
- Basile dlang-community (6/24) Jul 03 2017 There's been a small typo in my answer. "6.251" i meant obviously
- Era Scarecrow (6/7) Jul 02 2017 I almost wonder if a BCD, fixed length or alternative for
- H. S. Teoh via Digitalmars-d-learn (11/20) Jul 02 2017 floating-point for money calculations, and use fixed-point arithmetic
- Era Scarecrow (9/22) Jul 03 2017 It's been a while, i do recall there was BCD options, actually
- H. S. Teoh via Digitalmars-d-learn (11/25) Jul 03 2017 Wow, that brings back the memories... I used to dabble with BCD (only a
- Patrick Schluter (12/42) Jul 04 2017 In times of lore, BCD floats were very common. The Sharp Pocket
- Era Scarecrow (20/27) Jul 04 2017 If you look at the instruction set for 6502 (and probably similar
- Patrick Schluter (2/10) Jul 03 2017 IBM zSeries and POWER since POWER6 have BCD floating point unit...
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
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, Saurabh6.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
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:That explains it! Thank you.[...]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
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: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.On Monday, 3 July 2017 at 03:50:14 UTC, Saurabh Das wrote:That explains it! Thank you.[...]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 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.
Jul 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 usingfloating-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
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
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:[...]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.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
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: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.On Monday, 3 July 2017 at 06:20:22 UTC, H. S. Teoh wrote:[...]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.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 04 2017
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
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:IBM zSeries and POWER since POWER6 have BCD floating point unit...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 03 2017