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.

Reply via email to