Live data from Hacker News

0.30000000000000004

0.30000000000000004.com

31–40 of 422 posts

Re: 0.30000000000000004

#31

I still remember when I encountered this and nobody else in the office knew about it either. We speculated about broken CPUs and compilers until somebody found a newsgroup post that explained everything. Makes me wonder why we haven't switched to a better floating point model in the last decades. It will probably be slower but a lot of problems could be avoided.

Being a lot slower is a worse problem than being off by an error of 2^60. And if it isn't, then you simply choose a different numeric type.

Re: 0.30000000000000004

#32
post #17

I remember in college when we learned about this and I had the thought, "Why don't we just store the numerator and denominator?", and threw together a little C++ class complete with (then novel, to me) operator-overloads, which implemented the concept. I felt very proud of myself. Then years later I learned that it's a thing people actually use: https://en.wikipedia.org/wiki/Rational_data_type

But rationals are more expensive to compute with (compared to floating-point; this is another example of the trade-off between performance and accuracy.)

Re: 0.30000000000000004

#33
One small tip about printf for floating point numbers. In addition to "%f", you can also print them using "%g". While the precision specifier in %f refers to digits after the decimal period, in %g the precision refers to the number of significant digits. The %g version is also allowed to use exponential notation, which often results in more pleasant-looking output than %f.

   printf("%.4g", 1.125e10) --> 1.125e+10
   printf("%.4f", 1.125e10) --> 11250000000.0000

Re: 0.30000000000000004

#34

I still remember when I encountered this and nobody else in the office knew about it either. We speculated about broken CPUs and compilers until somebody found a newsgroup post that explained everything. Makes me wonder why we haven't switched to a better floating point model in the last decades. It will probably be slower but a lot of problems could be avoided.

Unless you have a floating point model that supports arbitrary bases, you're always going to have the issue. Binary floats are unable to represent 1/10 just as decimal floats are unable to represent 1/3. And in case anyone's wondering about handling it by representing the repeating digits instead, here's the decimal representation of 1/12345 using repeating digits: 0.0[000810044552450384771162413932766302146618063993…

> Unless you have a floating point model that supports arbitrary bases

See also binary coded decimals.

https://en.wikipedia.org/wiki/Binary-coded_decimal

Re: 0.30000000000000004

#35
Fixed-point calculations seem to be somewhat of a lost art these days.

It used to be widespread because floating point processors were rare and any floating point computation was costly.

That's not longer the case and everyone seems to immediately use floating point arithmetic without being fully aware of the limitations and/or without considering the precision needed.

Re: 0.30000000000000004

#36
> It's actually pretty simple

The explanation then goes on to be very complex. e.g. "it can only express fractions that use a prime factor of the base".

Please don't say things like this when explaining things to people, it makes them feel stupid if it doesn't click with the first explanation.

I suggest instead "It's actually rather interesting".

Re: 0.30000000000000004

#37
post #2

This is a good thing to be aware of. Also the "field" of floating point numbers is not commutative†, (can run on JS console:) x=0;for (let i=0; i --> 1.000000000000001 x=1;for (let i=0; i --> 1 Although most of the time a+b===b+a can be relied on. And for most of the stuff we do on the web it's fine!†† † edit: Please s/commutative/associative/, thanks for the comments below. †† edit: that's wrong! Replace with (a+b)+…

Isn't that more of an associativity problem than a commutativity problem, though?

1.0 + 1e-16 == 1e-16 + 1.0 == 1.0 as well as 1.0 + 1e-15 == 1e-15 + 1.0 == 1.000000000000001

however (1.0 + (1e-16 + 1e-16)) == 1.0 + 2e-16 == 1.0000000000000002, whereas ((1.0 + 1e-16) + 1e-16) == 1.0 + 1e-16 == 1.0

Re: 0.30000000000000004

#38
post #2

This is a good thing to be aware of. Also the "field" of floating point numbers is not commutative†, (can run on JS console:) x=0;for (let i=0; i --> 1.000000000000001 x=1;for (let i=0; i --> 1 Although most of the time a+b===b+a can be relied on. And for most of the stuff we do on the web it's fine!†† † edit: Please s/commutative/associative/, thanks for the comments below. †† edit: that's wrong! Replace with (a+b)+…

> Also the "field" of floating point numbers is not commutative, (can run on JS console:) OK. >> x = 0; 0 >> for (let i=0; i > x + 1 1.000000000000001 >> 1 + x 1.000000000000001 You've identified a problem, but it isn't that addition is noncommutative.

Yeah, what is demonstrated here is that floating point addition is nonassociative.

Re: 0.30000000000000004

#39
This is a great shibboleth for identifying mature programmers who understand the complexity of computers, vs arrogant people who wonder aloud how systems developers and language designers could get such a "simple" thing wrong.

Re: 0.30000000000000004

#40
post #17

I remember in college when we learned about this and I had the thought, "Why don't we just store the numerator and denominator?", and threw together a little C++ class complete with (then novel, to me) operator-overloads, which implemented the concept. I felt very proud of myself. Then years later I learned that it's a thing people actually use: https://en.wikipedia.org/wiki/Rational_data_type

Reminds me of this Inigo Quilez article on experimenting with rendering using rational numbers: https://iquilezles.org/www/articles/floatingbar/floatingbar....

I actually ran into a bug recently while implementing my first raytracer, where the point calculated from the sphere-intersect test would just occasionally end up inside the sphere due to floating point imprecision, so the diffuse sample rays would have their origins completely in the dark, leading to randomly black pixels. Solved it by bumping every intersection out by 0.01 in the direction of its normal.

And then of course there have been several other "x.abs() < 0.01" cases for various purposes. So I could definitely see that being an interesting experiment.

Post reply on HN