Live data from Hacker News

0.1 and 0.2 Returns 0.30000000000000004 (2018)

qntm.org

11–20 of 161 posts

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#11
post #7
post #5

Earlier quoted context omitted.

Misunderstanding floating point is more harmful than floating point itself.

Hence why it's harmful.

Floating point is fine. Non-integers are inherently tricky to represent, especially when you have to pack it into 32 bits. You could maybe quibble with some of the decisions around NaN and denormals and things like that, but mostly IEEE-754 got it right. There's a reason it's been the standard for three and a half decades now, and it's served the computer industry very well.

Incidentally: the fact that 0.1+0.2 does not equal 0.3 is not something you could quibble with, that is absolutely reasonable for a floating point standard. It would be insanity to base it off of base 10 instead of base 2.

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#12
post #2

Floating point considered harmful Edit: this is not a blanket statement. It was meant in the context.

"People repeating stuff without understanding it considered harmful."

Floating point is extremely useful. Too bad so many people have no idea how and when to use it. Including some people that design programming languages.

Please, tell me, mister, how would you perform complex numerical calculations efficiently?

I guess we should just forget about drones and bunch other stuff because 90% of developers have no clue how to use FP?

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#13
post #4

Not in Raku it doesn't! > 1.1 + 2.2 3.3 > 1.1 + 2.2 == 3.3 True EDIT: to be clear: this is not because Raku is magic, it's because Raku defaults to a rational number type for decimal literals, which is arguably a much better choice for a language like Raku.

Ahem, this is about 0.1 + 0.2. I think Raku also uses IEEE 754 double precision floating point numbers for the Num type, no?

Edit: it seems that Raku uses rationals as a default [1], so it doesn't suffer from the same problem by default.

[1]: https://0.30000000000000004.com/#raku

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#16
This just has to do with printing.

  This is the TXR Lisp interactive listener of TXR 256.
  Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
  TXR works even if the application surface is not free of dirt and grease.
  1> (+ 0.1 0.2)
  0.3
OK, so then:

  2> (set *print-flo-precision* 17)
  17
  3> (+ 0.1 0.2)
  0.30000000000000004
But:

  4> 0.1
  0.10000000000000001
  5> 0.2
  0.20000000000000001
  6> 0.3
  0.29999999999999999

I.e. 0.1 isn't exactly 0.1 and 0.2 isn't exactly 0.2 in the first place! The misleading action is to compare the input notation of 0.1 and 0.2 to the printed output of the sum, rather than consistently compare nothing but values printed using the same precision.

The IEEE double format can store 15 decimal digits of precision such that all those decimal digits are recoverable. If we print values to no more than 15 digits, then things look "artificially clean" for situations like (+ 0.1 0.2).

I made *print-flo-precision* have an initial value of 15 for this reason.

The 64 bit double gives us 0.1, 0.2 and 0.3 to 15 digits of precision. If we round at that many digits, we don't see the trailing junk of representational error.

Unfortunately, to 15 digits of precision, the data type gives us two different 0.3's: the 0.299999... one and the 0.3.....04 one. Thus:

  7> (= (+ 0.1 0.2) 0.3)
  nil
That's the real kicker; not so much the printing. This representational issue bites you regardless of what precision you print with and is the reason why there are situations in which you cannot compare floating-point values exactly.

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#17
post #11
post #7

Earlier quoted context omitted.

Hence why it's harmful.

Floating point is fine. Non-integers are inherently tricky to represent, especially when you have to pack it into 32 bits. You could maybe quibble with some of the decisions around NaN and denormals and things like that, but mostly IEEE-754 got it right. There's a reason it's been the standard for three and a half decades now, and it's served the computer industry very well. Incidentally: the fact that 0.1+0.2 does n…

Of course it shouldn't be base 10. It should be base 60. That has more prime factors and wastes fewer bits than BCD does.

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#18
post #11
post #7

Earlier quoted context omitted.

Hence why it's harmful.

Floating point is fine. Non-integers are inherently tricky to represent, especially when you have to pack it into 32 bits. You could maybe quibble with some of the decisions around NaN and denormals and things like that, but mostly IEEE-754 got it right. There's a reason it's been the standard for three and a half decades now, and it's served the computer industry very well. Incidentally: the fact that 0.1+0.2 does n…

I think one of the problems today is that floating point remains the default even for scripting languages like python. I'd wager that the huge majority of users of floating point arithmetic in their programs actually want correct math rather than efficient operations. This feels a bit like Random vs SecureRandom. So many people use the default and then accidentally shoot themselves in the foot. IMO, for scripting languages we should have infinite precision math by default and then be able to use floating point if you really care about speed.

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#19
post #4

Not in Raku it doesn't! > 1.1 + 2.2 3.3 > 1.1 + 2.2 == 3.3 True EDIT: to be clear: this is not because Raku is magic, it's because Raku defaults to a rational number type for decimal literals, which is arguably a much better choice for a language like Raku.

The same goes in Common Lisp, but for very different reasons:

  * (= (+ 0.1 0.2) 0.3)
  T
In Common Lisp, there is a small epsilon used in floating-point equality: single-float-epsilon. When two numbers are within that delta, they are considered equal.

Meanwhile, in Rakudo, 0.1 is a Rat: a rational number where the numerator and denominator are computed.

You can actually get the same underlying behavior in Common Lisp:

  (= (+ 1/10 2/10) 3/10)
Sadly, not many recent languages have defaults as nice as those. Another example is Julia:

  julia> 1//10 + 2//10 == 3//10
  true
IMO, numerical computations should be correct by default, and fast in opt-in.

Re: 0.1 and 0.2 Returns 0.30000000000000004 (2018)

#20
Indeed, and therefore:

  0.1 + 0.2 != 0.3
You can check it in the JavaScript console.

This actually makes me wonder if anyone's ever attempted a floating-point representation that builds in an error range, and correctly propagated/amplified error over operations.

E.g. a simple operation like "1 / 10" (to generate 0.1) would be stored not as a single floating-point value, but really as the range between the closest representation greater than and less than it. The same with "2 / 10", and then when asking if 0.1 + 0.2 == 0.3, it would find an overlap in ranges between the left-hand and right-hand sides and return true. Every floating-point operation would then take and return these ranges.

Then floating point arithmetic could be used to actually reliably test equality without ever generating false negatives. And if you examined the result of calculation of 10,000 operations, you'd also be able to get a sense of how off it might maximally be.

I've search online and can't find anything like it, though maybe I'm missing an important keyword.

Post reply on HN