为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
蓝山帝景 2022-09-26 19:48:07
在过去的2周里,我一直在研究浮点的行为和功能,特别是GO中的大浮点。我遇到了许多行为,并自己找到了答案。但是,仍然有一个答案我找不到自己。https://play.golang.org/p/-y0oeb2Jisvvalue1 := 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)为什么这两个操作的结果不相等?根据我的理解,这与精度/准确性/舍入模式有关。
查看完整描述

1 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

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

比较大。浮点值(或 ),请使用浮点值。如果 2 个值(它们表示的数字)相等,则返回。*big.Float0

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() 返回的序列化二进制形式是不一样的,但这并不意味着表示的数字不相等。正如其文档所述:

戈布代码实现了这个贪婪。Gob编码器接口。将封送处理 Float 值及其所有属性(精度、舍入模式、准确性)。

输出是不同的,因为 的内部结构不相同(在本例中为精度)。在这种情况下,即使您可以比较指向的对象,这些对象也不会相同,但表示的数字是相同的。同样,始终使用提供的方法比较复杂对象,当然不是地址。big.Float

此示例中的差异来自存储的精度字段:

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

哪些输出(在Go游乐场上尝试):

Below
Exact

返回的精度是“最近操作产生的x的精度”。由于在 和 上执行的最后一个操作不相同( 和 ),因此精度字段不一定相同(并且在此示例中它们确实不同)。由于准确性属性也包含在 Gob 序列化表单中,因此它们的序列化表单不同。Float.Acc()value1value3value1.Sub()value3.Set()


查看完整回答
反对 回复 2022-09-26
  • 1 回答
  • 0 关注
  • 61 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信