Noting that what @Brian%20Candler just said is bang on, I'll add that if you use `math.Nextafter(y, math.Round(y))` or `y - math.Nextafter(math.Mod(y, 0.01), math.Round(y))`, you can clean up a poorly represented number. The following is Brian's example, but with those two algorithms presented: https://go.dev/play/p/C8qXVOO1jPY The first one will be faster always.
An alternative is to use an integer with a packed region as integral and an 8-12 bit decimal component. Call it 9 bits. That gives you a denominator for the remainder of 1024. To extract the packed value, you can use bitshift and bitwise and ops as follows: `fmt.Printf("v is %v.%vx", v >> 9, v & 1023)`, depending. If you're intrigued, try playing with different numbers here: https://www.rapidtables.com/convert/number/decimal-to-binary.html You should check "0.2" out at https://baseconvert.com/ieee-754-floating-point to understand what's happening. @bmhad threw a link at you that explains how floating point numbers work, but this lets you observe how specific numbers are stored, and why a specific number you want to store, such as 0.2, is a really, really hard. After checking that out, you'll understand why the algorithms I suggested help, and also why they might not always arrive at the precision you want. If this concerns you, do remember that any other On Monday, April 11, 2022 at 2:04:16 AM UTC-5 Brian Candler wrote: > According to the go spec > <https://tip.golang.org/ref/spec#Constant_expressions>: > "Constant expressions are always evaluated exactly; intermediate values > and the constants themselves may require precision significantly larger > than supported by any predeclared type in the language" > > Hence there's a difference between: > * doing an exact addition of 0.1 + 0.2 , then converting the exact value > 0.3 to a float64; versus > * converting 0.1 to float64, converting 0.2 to a float64, and then adding > them using float64 precision. > > https://go.dev/play/p/x7vf_064RUf > > On Sunday, 10 April 2022 at 22:16:21 UTC+1 wagner riffel wrote: > >> On Sat Apr 9, 2022 at 3:56 PM CEST, 'Jack Li' via golang-nuts wrote: >> > Why literal operation is exact, variable is not? >> > >> > fmt.Println(0.1 + 0.2) // 0.3 exactly >> > fmt.Println(x + y) // 0.30000000000000004 >> > >> >> Both aren't exact because floats can't represent 0.3 exactly, they >> differ because literals and constants expressions have arbitrary >> precision (http://golang.org/ref/spec/#Constants), so "0.1" and "0.2" >> in "0.1 + 0.2" are exact, then when the exact "0.3" result is >> converted to a float64 it becomes the closest possible, You can check >> this if you ask to print with more precision >> >> x, y := 0.1, 0.2 >> fmt.Printf("%.17f...\n", 0.1+0.2) // 0.29999999999999999... >> fmt.Printf("%.17f...\n", x+y) // 0.30000000000000004... >> >> https://go.dev/play/p/2qSfoCZGaD6 >> >> -w >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/83326013-f9ed-419e-9858-3ba3a061428cn%40googlegroups.com.