News for hackers. Stuff that matters.
Re:GCC Non-bugs by shortstuffsushi on Sunday March 01, 2015 @11:56PM (#9130396)
I know this is a problem with many programming languages, but why is there not a standard way to precisely represent decimal numbers? I understand the difficulty representing them in binary (well, kind of -- it's been a while since I read about it), but it seems like knowing this, a better solution would be found. Why is this accepted and standard behavior?
Re:GCC Non-bugs by McKayDavis on Monday March 02, 2015 @02:49AM (#9130787)
Are you familiar with the IEEE 754-2008 specification of decimal floating point format?

From Wikipedia's entry on decimal64[1]: "It is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations."

[1] http://en.wikipedia.org/wiki/Decimal64_floating-point_format

Re:GCC Non-bugs by shortstuffsushi on Monday March 02, 2015 @11:57AM (#9132838)
No, I was not. I'm assuming that the standard double or float do not conform to this spec, though, right?
Re:GCC Non-bugs by jordanb on Monday March 02, 2015 @02:47AM (#9130782)
Decimal numbers are supported by many languages (python has the Decimal library for instance).

The problem is that decimal isn't supported by modern hardware so it's not supported natively by C which adds very little to hardware representations.

Re:GCC Non-bugs by hendzen on Monday March 02, 2015 @12:47AM (#9130489)
Sure there is. It's called Binary-coded decimal, and its been around since the 60's (at the latest).
Re:GCC Non-bugs by cbd1984 on Monday March 02, 2015 @03:09AM (#9130847)
BCD is orthogonal to this.
Re:GCC Non-bugs by krzysz00 on Monday March 02, 2015 @12:04AM (#9130411)
If by "decimal numbers" you mean the reals written in base 10, how do you propose we precisely represent the result of 1 / 3 . Or pi?
Re:GCC Non-bugs by shortstuffsushi on Monday March 02, 2015 @12:22AM (#9130426)
I guess I wasn't necessary referring to solving the problem of non-terminating numbers, but more things like 0.1 * 0.2 = 0.020000000000000004 in Javascript, or the very first bug listed on the linked page.

Perhaps what you intend with that statement is that issues like that of 1/3 are a cause for these sorts of issues, but interestingly (at least in JS), 1/3 is terminating, and results in an "expected" value.

Re:GCC Non-bugs by krzysz00 on Monday March 02, 2015 @01:03AM (#9130520)
Well, every base has issues with non-termination. In base 10, we have problems like 1/3 = 0.33333... . Base 2 has its own set of non-terminating decimal expansions, including 1 / 3 = 0.01010101... and 1 / 10 = 0.0001100110011... . Since we only have finite storage space, we have to cut the repeating string of digits off somewhere, no matter what base we're in. This can cause rounding issues.

You can't dodge all your rounding problems by changing base. There are binary-coded decimal (BCD) systems that store numbers as strings of decimal digits. You can generally find these in calculators (ever notice that a TI-84 overflows after 9.(9)e99) or some financial software. However, you'll still have problems like the 0.1 * 0.2 issue in binary floating-point. For example (assuming shorter-than-usual numbers):

2/3 = 0.66... ~ 0.66667

2/3 + 2/3 ~ 0.66667 + 0.66667 = 1.33334

However, 4/3 = 1.33333... ~ 1.33333, which isn't the same result.

Basically, you can't get away from this problem, you can only push it around to cases you care less about.

(You probably can't find an API for binary-coded decimal in $LANGUAGE unless $LANGUAGE is often used for tasks where you really really don't want any float-related gotchas since most everyone else doesn't care too much).

Re:GCC Non-bugs by edwintorok on Monday March 02, 2015 @03:18AM (#9130874)
You could represent your numbers as fractions of integers and do all operations on them as fractions of integers: https://gmplib.org/manual/Rational-Number-Functions.html#Rat...

And only converting them to floating point for display purposes: http://www.mpfr.org/mpfr-current/mpfr.html#index-mpfr_005fse...

Re:GCC Non-bugs by shortstuffsushi on Monday March 02, 2015 @11:44AM (#9132736)
Hmm, so BCD seems closer to what I was roughly imagining (though, I haven't really thought this issue through deeply or anything), but you mention it has shortcomings as well. I guess I'll just have to trust that other people have thought about this, and have determined this to be the best solution, even with its flaws.
Re:GCC Non-bugs by dietrichepp on Monday March 02, 2015 @12:52AM (#9130497)
The result of the computation 1/3 in JS results in a number which is terminating, but that number is not 1/3. Open up your console and type 1/3+1/3+1/3... 1, as expected. Then type 1-1/3-1/3-1/3... I get about 1e-16, which is not 0.

The statement that "1/3 is terminating" is not true in binary, it is not true in decimal, and the only reason that you sometimes get the expected results is that sometimes the rounding errors will cancel out.

Re:GCC Non-bugs by shortstuffsushi on Monday March 02, 2015 @11:59AM (#9132854)
I realize that 1/3 is not terminating in decimal, what I meant was that in JS, it seemed to end neatly after x decimal places, which I found interesting. I hadn't tried the operation you mentioned until you posted that, the results are even more bizarre to me. Seems I need to spend some time relearning floating point math to better understand what I'm seeing.
Re:GCC Non-bugs by valleyer on Monday March 02, 2015 @02:52AM (#9130796)
So you're telling me we should use base 3.
Re:GCC Non-bugs by jakobegger on Monday March 02, 2015 @03:29AM (#9130909)
Well then 0.5 would be non-terminating...
Re:GCC Non-bugs by tbirdz on Monday March 02, 2015 @12:26AM (#9130438)
floating point is just one way of representing non-integral numbers, you can also use fixed point, rational types (integer numerator and denominator), and there are also types for arbitrary precision decimals, like gmp or BigDecimal.