Re: [go-nuts] float exactness

2022-04-11 Thread Sam Hughes
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 
> :
> "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.30004 
>> > 
>>
>> 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.2... 
>> fmt.Printf("%.17f...\n", x+y) // 0.30004... 
>>
>> 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.


Re: [go-nuts] float exactness

2022-04-11 Thread Brian Candler
According to the go spec 
:
"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.30004
> >
>
> 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.2...
> fmt.Printf("%.17f...\n", x+y) // 0.30004...
>
> 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/a487a8bb-caf7-4b74-b81c-93d3d689a5ecn%40googlegroups.com.


Re: [go-nuts] float exactness

2022-04-10 Thread 'wagner riffel' via golang-nuts
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.30004
>

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.2...
fmt.Printf("%.17f...\n", x+y) // 0.30004...

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/CJ6VDO2DK4XB.3VDUG02EUZ58S%40pampas.


Re: [go-nuts] float exactness

2022-04-09 Thread 'Jack Li' via golang-nuts
Thanks Robert,


It is great!


a, _ := decimal.NewFromString("0.1")
b, _ := decimal.NewFromString("0.2")
c := a.Add(b)
fmt.Println("decimal:", c)


a = decimal.NewFromFloat(0.1)
b = decimal.NewFromFloat(0.2)
c = a.Add(b)
fmt.Println("decimal:", c)


a, _ = decimal.NewFromString("0.1")
b, _ = decimal.NewFromString("0.35")
c = a.Add(b)
fmt.Println("decimal:", c)


a = decimal.NewFromFloat(0.1)
b = decimal.NewFromFloat(0.35)
c = a.Add(b)
fmt.Println("decimal:", c)



/*
$ go build  ./main
decimal: 0.3
decimal: 0.3
decimal: 0.45
decimal: 0.45
$

*/




--Original--
From: "Robert Engels"https://groups.google.com/d/msgid/golang-nuts/tencent_327903B1334351F91FC17D18F2C6E1937508%40qq.com.
 
 

 -- 
 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/A7E20597-1DED-4666-BAFA-7F5F79F43A0E%40ix.netcom.com.

-- 
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/tencent_B33EB1034311F99BC168183BC67393717908%40qq.com.


Re: [go-nuts] float exactness

2022-04-09 Thread Brian Hatfield
Here's a more general explanation of why floating point operations didn't
do what you expected: https://floating-point-gui.de/basic/

On Sat, Apr 9, 2022 at 9:56 AM 'Jack Li' via golang-nuts <
golang-nuts@googlegroups.com> wrote:

> Hi group,
>
> 1.
> Is there a package can do exact float operations, like Decimal in Python?
> For example:
>
> x := 0.1; y := 0.2; z := x + y;
>
> z will be exact 0.3
>
> 2.
> Why literal operation is exact, variable is not?
>
> fmt.Println(0.1 + 0.2) // 0.3 exactly
>
> fmt.Println(x + y) // 0.30004
>
>
> Thanks
>
>
> func main() {
> x := 0.1
> y := 0.2
> fmt.Println("x + y  :", x   + y)
> fmt.Println("literal:", 0.1 + 0.2)
>
> x = 0.1
> y = 0.35
> fmt.Println("x + y  :", x   + y)
> fmt.Println("literal:", 0.1 + 0.35)
> }
>
> /*
> $ go build && ./main
> x + y  : 0.30004
> literal: 0.3
> x + y  : 0.44996
> literal: 0.45
> $
> */
>
>
> // Python:
>
> // >>> 0.1 + 0.2
> // 0.30004
>
> // >>> float(Decimal('0.1') + Decimal('0.2'))
> // 0.3
> // >>>
>
> // >>> 0.35 + 0.1
> // 0.44996
>
> // >>> float(Decimal('0.35') + Decimal('0.1'))
> // 0.45
> // >>>
>
> --
> 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/tencent_327903B1334351F91FC17D18F2C6E1937508%40qq.com
> 
> .
>

-- 
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/CANGiwgbAGa9fsweTCsJ11WJkuQH7U-qhafjc85442nTzLTzqNQ%40mail.gmail.com.


Re: [go-nuts] float exactness

2022-04-09 Thread Robert Engels
There are several. 

See github.com/robaho/fixed

As to why, read up on numerical analysis. It’s an interesting topic. 

> On Apr 9, 2022, at 8:56 AM, 'Jack Li' via golang-nuts 
>  wrote:
> 
> 
> Hi group,
> 
> 1. 
> Is there a package can do exact float operations, like Decimal in Python? For 
> example:
> 
> x := 0.1; y := 0.2; z := x + y;
> 
> z will be exact 0.3
> 
> 2.
> Why literal operation is exact, variable is not?
> 
> fmt.Println(0.1 + 0.2) // 0.3 exactly
> 
> fmt.Println(x + y) // 0.30004
> 
> 
> Thanks
> 
> 
> func main() {
>   x := 0.1
>   y := 0.2
>   fmt.Println("x + y  :", x   + y)
>   fmt.Println("literal:", 0.1 + 0.2)
> 
>   x = 0.1
>   y = 0.35
>   fmt.Println("x + y  :", x   + y)
>   fmt.Println("literal:", 0.1 + 0.35)
> }
> 
> /*
> $ go build && ./main
> x + y  : 0.30004
> literal: 0.3
> x + y  : 0.44996
> literal: 0.45
> $ 
> */
> 
> 
> // Python:
> 
> // >>> 0.1 + 0.2
> // 0.30004
> 
> // >>> float(Decimal('0.1') + Decimal('0.2'))
> // 0.3
> // >>>
> 
> // >>> 0.35 + 0.1
> // 0.44996
> 
> // >>> float(Decimal('0.35') + Decimal('0.1'))
> // 0.45
> // >>>
> 
> -- 
> 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/tencent_327903B1334351F91FC17D18F2C6E1937508%40qq.com.

-- 
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/A7E20597-1DED-4666-BAFA-7F5F79F43A0E%40ix.netcom.com.


[go-nuts] float exactness

2022-04-09 Thread 'Jack Li' via golang-nuts
Hi group,


1.
Is there a package can do exact float operations, like Decimal in Python? For 
example:


x := 0.1; y := 0.2; z := x + y;


z will be exact 0.3


2.
Why literal operation is exact, variable is not?


fmt.Println(0.1 + 0.2) // 0.3 exactly


fmt.Println(x + y) // 0.30004




Thanks




func main() {
x := 0.1
y := 0.2
fmt.Println("x + y :", x  + y)
fmt.Println("literal:", 0.1 + 0.2)


x = 0.1
y = 0.35
fmt.Println("x + y :", x  + y)
fmt.Println("literal:", 0.1 + 0.35)
}


/*
$ go build  ./main
x + y : 0.30004
literal: 0.3
x + y : 0.44996
literal: 0.45
$
*/




// Python:


//  0.1 + 0.2
// 0.30004


//  float(Decimal('0.1') + Decimal('0.2'))
// 0.3
// 


//  0.35 + 0.1
// 0.44996


//  float(Decimal('0.35') + Decimal('0.1'))
// 0.45
// 

-- 
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/tencent_327903B1334351F91FC17D18F2C6E1937508%40qq.com.