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

如何将 float64 数字截断为特定精度?

如何将 float64 数字截断为特定精度?

Go
繁星coding 2023-06-01 18:11:49
我想截断1.234567成一个三位数的浮点数,但结果不是我想要的。例如:1.234567=>1.234package mainimport (    "strconv"    "fmt")func main() {    f := 1.234567    fmt.Println(strconv.FormatFloat(f, 'f', 3, 64)) //1.235    fmt.Printf("%.3f", f) //1.235}谁能告诉我如何在 Go 中执行此操作?
查看完整描述

2 回答

?
森林海

TA贡献2011条经验 获得超2个赞

天真的方式(并不总是正确的)

对于截断,我们可以利用math.Trunc()它丢弃小数位。这不是我们想要的,我们想要保留一些小数位。所以为了达到我们想要的效果,我们可以先将输入乘以 10 的幂,将想要的小数位移动到“整数”部分,然后截断(调用 which 会丢弃剩余的小数位),我们math.Trunc()可以除以我们在开始时乘以的 10 的相同次方:

f2 := math.Trunc(f*1000) / 1000

将其包装成一个函数:

func truncateNaive(f float64, unit float64) float64 {
    return math.Trunc(f/unit) * unit
}

测试它:

f := 1.234567
f2 := truncateNaive(f, 0.001)
fmt.Printf("%.10f\n", f2)

输出:

1.2340000000

到目前为止一切顺利,但请注意,我们在内部执行算术运算truncateNaive()可能会导致不需要的舍入,这可能会改变函数的输出。

例如,如果输入是0.299999999999999988897769753748434595763683319091796875(它可以float64准确地由一个值表示,请参阅证明),则输出应该是0.2999000000,但它会是其他东西:

f = 0.299999999999999988897769753748434595763683319091796875
f2 = truncateNaive(f, 0.001)
fmt.Printf("%.10f\n", f2)

输出:

0.3000000000

在Go Playground上试试这些。

在大多数情况下,这种错误的输出可能是不可接受的(除非你从输入非常接近——0.3差异小于 10 -16——输出是0.3……的方式来看它)。

使用big.Float

要正确截断所有有效值float64,中间操作必须精确。要实现这一目标,仅使用一个float64是不够的。有一些方法可以将输入拆分为 2 个float64值并对它们执行操作(因此精度不会丢失)这会更有效,或者我们可以使用更方便的方法,big.Float它可以是任意精度。

truncateNaive()这是上述函数的“抄本” big.Float

func truncate(f float64, unit float64) float64 {

    bf := big.NewFloat(0).SetPrec(1000).SetFloat64(f)

    bu := big.NewFloat(0).SetPrec(1000).SetFloat64(unit)


    bf.Quo(bf, bu)


    // Truncate:

    i := big.NewInt(0)

    bf.Int(i)

    bf.SetInt(i)


    f, _ = bf.Mul(bf, bu).Float64()

    return f

}

测试它:


f := 1.234567

f2 := truncate(f, 0.001)

fmt.Printf("%.10f\n", f2)


f = 0.299999999999999988897769753748434595763683319091796875

f2 = truncate(f, 0.001)

fmt.Printf("%.10f\n", f2)

输出现在有效(在Go Playground上尝试):


1.2340000000

0.2990000000


查看完整回答
反对 回复 2023-06-01
?
侃侃无极

TA贡献2051条经验 获得超10个赞

您需要在字符串级别或类似math.Floor https://play.golang.org/p/UP2gFx2iFru手动截断小数。



查看完整回答
反对 回复 2023-06-01
  • 2 回答
  • 0 关注
  • 177 浏览
慕课专栏
更多

添加回答

举报

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