Golang:如何处理浮点数?

时间:2015-11-20 16:38:02

标签: algorithm go precision

当开始使用浮点类型(float32& float64)时,我感到非常惊讶。 在这个例子中,我只从集合中收集了几个选项:

package main

import (
    "fmt"
)

func main() {
    var sum, price, count float64
    sum, price, count = 1000, 166.67, 5
    fmt.Printf("%v - %v * %v = %v\n", sum, price, count, sum-price*count)
    price, count = 7.35, 3
    fmt.Printf("%v * %v = %v\n", price, count, price*count)
    var a, b, c float64
    a, b = 2, 1.1
    fmt.Printf("%v - %v = %v\n", a, b, a-b)
    a, b, c = 0.1, 0.2, 0.3
    fmt.Printf("%v + %v - %v = %v\n", a, b, c, a+b-c)
}

打印:

1000 - 166.67 * 5 = 166.6500000000001
7.35 * 3 = 22.049999999999997
2 - 1.1 = 0.8999999999999999
0.1 + 0.2 - 0.3 = 5.551115123125783e-17
2.4 / 0.1 = 23.999999999999996

执行算术运算后出现问题:+, - ,*,/

现在我绝对不确定我的算法会给我正确的结果。

我通过在每次操作后对值进行归一化来解决问题 - 舍入到比错误更低的精度:

package main

import (
    "fmt"
    "math"
)

func main() {
    var sum, price, count float64
    sum, price, count = 1000, 166.67, 5
    fmt.Printf("%v - %v * %v = %v\n", sum, price, count, Normalize(sum-price*count))
    price, count = 7.35, 3
    fmt.Printf("%v * %v = %v\n", price, count, Normalize(price*count))
    var a, b, c float64
    a, b = 2, 1.1
    fmt.Printf("%v - %v = %v\n", a, b, Normalize(a-b))
    a, b, c = 0.1, 0.2, 0.3
    fmt.Printf("%v + %v - %v = %v\n", a, b, c, Normalize(a+b-c))
    a, b = 2.4, 0.1
    fmt.Printf("%v / %v = %v\n", a, b, Normalize(a/b))
}

func Normalize(value float64) float64 {
    return RoundViaFloat(value, 4)
}

func RoundViaFloat(x float64, prec int) float64 {
    var rounder float64
    pow := math.Pow(10, float64(prec))
    intermed := x * pow
    _, frac := math.Modf(intermed)
    x = .5
    if frac < 0.0 {
        x = -.5
    }
    if frac >= x {
        rounder = math.Ceil(intermed)
    } else {
        rounder = math.Floor(intermed)
    }
    return rounder / pow
}

打印:

1000 - 166.67 * 5 = 166.65
7.35 * 3 = 22.05
2 - 1.1 = 0.9
0.1 + 0.2 - 0.3 = 0
2.4 / 0.1 = 24

但在我看来,这是不正常的: - (

任何人都可以帮我解决这个问题吗?

感谢名单

0 个答案:

没有答案