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

带有浮点数的 GoLang for 循环会产生错误

带有浮点数的 GoLang for 循环会产生错误

蝴蝶刀刀 2021-06-29 13:04:38
有人可以解释以下内容。我在 go 中有一个函数,它接受几个 float64,然后使用这个值来计算许多其他值。该功能看起来像func (g *Geometry) CalcStresses(x, zmax, zmin float64)(Vertical)结果被放入一个结构中type Vertical struct {    X float64    Stresses []Stress}现在有趣的是这个。如果我这样调用函数;for i:=14.0; i<15.0; i+=0.1{    result := geo.CalcStresses(i, 10, -10)}然后我得到很多结果,其中 Stress 数组为空,另一个有趣的细节是 x 有时显示为带有很多小数的数字(如 14.399999999999999998)但是,如果我这样调用函数;for i:=0; i<10; i++{    x := 14.0 + float64(i) * 0.1    result := geo.CalcStresses(x,10,-10)}那么一切都很好。有谁知道为什么会这样?
查看完整描述

1 回答

?
皈依舞

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

并非所有实数都可以用二进制浮点格式精确表示,因此在浮点数上循环会带来麻烦。


来自维基百科上的浮点数


浮点数无法精确表示所有实数,并且浮点运算无法精确表示真正的算术运算,这一事实导致了许多令人惊讶的情况。这与计算机通常表示数字的有限精度有关。


例如,0.1 和 0.01(二进制)的不可表示性意味着尝试平方 0.1 的结果既不是 0.01,也不是最接近它的可表示数。


for i := 14.0; i < 15.0; i += 0.1 {

    fmt.Println(i)

}

产生这个


14

14.1

14.2

14.299999999999999

14.399999999999999

14.499999999999998

14.599999999999998

14.699999999999998

14.799999999999997

14.899999999999997

14.999999999999996

您可以使用math.big.Rat类型来准确表示有理数。


x := big.NewRat(14, 1)

y := big.NewRat(15, 1)

z := big.NewRat(1, 10)


for i := x; i.Cmp(y) < 0; i = i.Add(i, z) {

    v, _ := i.Float64()

    fmt.Println(v)

}


查看完整回答
反对 回复 2021-07-12
  • 1 回答
  • 0 关注
  • 129 浏览

添加回答

举报

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