为什么这两个大Float值不相等?



在过去的两周里,我一直在研究浮点数的行为和功能,特别是GO中的大浮点数。我遇到了无数的行为,我自己找到了答案。但是,有一个答案是我自己找不到的。

https://play.golang.org/p/-y0oeb2Jisv

value1 := big.NewFloat(137216723432.8234782347)
value2 := big.NewFloat(71371.92602458)
for i := 0; i < 300; i++ {
value1.Sub(value1, value2)
}
value3 := big.NewFloat(137216723432.8234782347)
value4 := big.NewFloat(71371.92602458)
for i := 0; i < 300; i++ {
result := big.NewFloat(0).Sub(value3,value4)
value3.Set(result)
}
encodedValue1, _ := value1.GobEncode()
encodedValue3, _ := value3.GobEncode()
if value1 == value3 {
fmt.Println("values are equal" , value1 , value3)
} else {
fmt.Println("values are not equal", value1 ,value3)
}
fmt.Println("difference is here:n", encodedValue1,"n", encodedValue3)

为什么这两个操作的结果不相等?根据我的理解,这与精度/精度/舍入模式有关。

谢谢!

value1value3是指针,因此value1 == value3比较的是这些指针,而不是指向的值。有可能两个有指向的对象是相等的,但它们的地址不相等。

要比较big.Float值(或*big.Float),请使用Float.Cmp()方法。如果两个值(它们所代表的数字)相等,则返回0

if value1.Cmp(value3) == 0 {
fmt.Println("values are equal", value1, value3)
} else {
fmt.Println("values are not equal", value1, value3)
}

修改后的输出将是(在Go Playground上试试):

values are equal 1.3719531185501585e+11 1.3719531185501585e+11
difference is here:
[1 2 0 0 0 53 0 0 0 37 255 139 210 151 120 32 120 0] 
[1 10 0 0 0 53 0 0 0 37 255 139 210 151 120 32 120 0]

表示的数字是相等的。

Float.GobEncode()返回的序列化二进制形式不相同,但这并不意味着表示的数字不相等。如其文档所述:

GobEncode实现了gob。GobEncoder接口。Float值及其所有属性(精度、舍入模式、精度)将被封送。

输出是不同的,因为big.Float的内部是不一样的(在这个例子中是Accuracy)。在这种情况下,即使您可以比较有指向的对象,它们也不会相同,但表示的数字是相同的。同样,总是使用提供的方法来比较复杂的对象,而不是地址。

这个例子中的区别来自于存储的精度字段:

fmt.Println(value1.Acc())
fmt.Println(value3.Acc())

哪个输出(在Go Playground上试试):

Below
Exact

Float.Acc()返回的精度是最近一次操作产生的x的精度。由于对value1value3执行的最后一次操作不相同(value1.Sub()value3.Set()),因此精度字段不一定相同(在本例中它们确实不同)。由于精度属性也包含在Gob序列化形式中,这就是为什么它们的序列化形式是不同的。

相关内容

  • 没有找到相关文章

最新更新