for-loop - 带有 float 的 GoLang for 循环会产生错误

标签 for-loop floating-point go rounding

谁能解释一下。我在 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.3999999999999999998)

但是,如果我这样调用函数;

for i:=0; i<10; i++{
    x := 14.0 + float64(i) * 0.1
    result := geo.CalcStresses(x,10,-10)
}

那么一切都很好。

有人知道为什么会这样吗?

提前致谢, 罗布

最佳答案

并非所有的实数都可以用二进制浮点格式精确表示,因此循环 float 是自找麻烦。

来自 Floating point 上的维基百科

The fact that floating-point numbers cannot precisely represent all real numbers, and that floating-point operations cannot precisely represent true arithmetic operations, leads to many surprising situations. This is related to the finite precision with which computers generally represent numbers.

For example, the non-representability of 0.1 and 0.01 (in binary) means that the result of attempting to square 0.1 is neither 0.01 nor the representable number closest to it.

This code

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类型以准确表示有理数。

Example

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)
}

关于for-loop - 带有 float 的 GoLang for 循环会产生错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20517647/

相关文章:

javascript - 尝试遍历数组并为每个数组添加一个 get 函数

javascript - 将 JavaScript 对象列表显示为 HTML 列表项

python - 打印 Python 和 C++ double 时的精度差异

go - 如何在实时应用程序 RethinkDB 上访问/安装/设置 Web 面板

go - golang中有 "using"吗?

python - 遍历字符串时是否保证执行顺序?

r - 在R中的for循环中向列表中添加元素

mysql - MySQL 存储函数中的 FLOAT 类型可以被截断吗?

C float直译

rest - 如何在 Go HTTP 服务器中有条件地设置 HTTP 状态代码?