猿问

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

有人可以解释以下内容。我在 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)

}

那么一切都很好。


有谁知道为什么会这样?


蝴蝶刀刀
浏览 130回答 1
1回答

皈依舞

并非所有实数都可以用二进制浮点格式精确表示,因此在浮点数上循环会带来麻烦。来自维基百科上的浮点数浮点数无法精确表示所有实数,并且浮点运算无法精确表示真正的算术运算,这一事实导致了许多令人惊讶的情况。这与计算机通常表示数字的有限精度有关。例如,0.1 和 0.01(二进制)的不可表示性意味着尝试平方 0.1 的结果既不是 0.01,也不是最接近它的可表示数。for i := 14.0; i < 15.0; i += 0.1 {&nbsp; &nbsp; fmt.Println(i)}产生这个1414.114.214.29999999999999914.39999999999999914.49999999999999814.59999999999999814.69999999999999814.79999999999999714.89999999999999714.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) {&nbsp; &nbsp; v, _ := i.Float64()&nbsp; &nbsp; fmt.Println(v)}
随时随地看视频慕课网APP

相关分类

Java
我要回答