6 ms·
Go is actually a lot more confusing about this than this than this page makes clear. a := .1; b := .2 fmt.Println(a+b) returns 0.30000000000000004 fmt.Printl
by jfindley 11y ago
Go is actually a lot more confusing about this than this than this page makes clear.
a := .1; b := .2
fmt.Println(a+b) returns 0.30000000000000004
fmt.Println(.1+.2) returns 0.3
Even worse, this persists into comparisons:
c := .3
a+b == c returns false
.1+.2 == c returns true
It's not a particularly big issue, mostly, but I'm sure it's confused someone before now, and will do so again.
Demo code: http://play.golang.org/p/FOv0JQRQJN http://play.golang.org/p/FOv0JQRQJN
- sacado2 11y agoYay that's weird. Where's the magic?
- dmit 11y agoNumeric literals in Go are untyped until they need to be. https://blog.golang.org/constants https://blog.golang.org/constants
- 1wd 11y agoGo is specified to calculate constant expressions with higher precision (256 bits of mantissa). https://golang.org/ref/spec#Constants https://golang.org/ref/spec#Constants
- jacquesm 11y agoOne should never compare for equality on floats or doubles, with the possible exception of '0' depending on the context.
- tomp 11y agoDon't be ridiculous. It's perfectly fine if you know what you're doing. For example, when you have a limited selection of floats (e.g. hashtable keys, or only numbers between 0 and 100, accurate to 1 decimal) - in these cases, strings would work just as well, but floats are more efficient (and compare correctly).
- jacquesm 11y agoYou've just redefined your problem to using floats as the underlying representation. In that case you don't even need floats... In most other cases the correct way is to check if the absolute value of the difference between one value and another is smaller than some arbitrary cut-off, a small number typically denoted with 'epsilon'.
- tomp 11y agoI don't need floats, but they're useful. E.g. for comparison, as I wrote above.
- jacquesm 11y agoUntil your code gets ported to a platform where float == double and it turns out the algo feeding your clever efficient comparison delivers slightly different values that previously collapsed into the same bucket. Relying on the particulars of an underlying representation requires deep knowledge of how those particulars are implemented (and I would happily agree with you that such knowledge is a requirement but more often than not when you come across a float comparison with equality you're looking at a bug. That you're the exception to the rule is fine with me, you seem to know what you're doing so don't take it personal). The real problem is: most people don't have deep knowledge of how those details are implemented and take 'equality' for granted, especially if the visual representation of the numbers they are comparing tells them they should be equal which is not always the case. The old adage goes: if you need floating point you don't understand your problem :) The comment that sparked this sub-thread is a nice illustration of what can and does go wrong.
- f2f 11y agotry " fmt.Printf("%.50f\n", .1+.2)"