Golang中float32转字符串的问题如何解决

Golang中float32转字符串的问题如何解决 我在将float32转换为字符串时遇到了问题。 我的测试代码:

package main
import (
	"fmt"
	"strconv"
)

func main() {
    var t float32
    t = 5.9902389
	numeroString := strconv.FormatFloat(float64(t), 'f', -1, 32)
	fmt.Println("Number float32:", t)
	fmt.Println("Number string:", numeroString)
}

响应: Number float32: 5.9902387 Number string: 5.9902387

对我来说,期望的响应是“5.9902389”。如何在不了解数字精度的情况下,获取float32的精确字符串表示?

我没有固定的小数位数。 提前感谢。


更多关于Golang中float32转字符串的问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

11 回复

固定点、小数、整数。

更多关于Golang中float32转字符串的问题如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢您的帮助

如果你需要八位数的精度

如果你需要精度,就不要使用浮点数。

显著性通常以十进制位数指定,而非二进制。如果需要精确性,不应使用浮点数。

“如果你需要精确度,就不要使用浮点数。” 那么,追求精确度的更好方法是什么?

我得到了你截图中显示的内容,不过我的理解是,原帖作者期望打印出相同的数字,但实际上得到了不同的结果……

该包支持 Decimal 类型:GitHub - shopspring/decimal: Go 语言中的任意精度定点十进制数 Go 语言有对应的内置类型吗?

物理测量具有特定的有效数字位数。你不需要比有效数字位数更多的数字。数值分析建立在计算基础上,旨在将浮点运算带来的误差降低到可容忍的水平。科学计算在浮点数上表现良好。金融应用或其他应用可能有所不同。如果你需要性能,那么不要使用任意精度。

无法在Go Playground上复现此问题…

Go Playground - The Go Programming Language

此处的程序产生了(你)预期的结果。

不过,由于这是浮点数,无论你得到什么结果,本质上都是不精确的。确切的数字无法用float32精确表示。可以使用IEEE-754浮点数转换器来检查实际存储的精确数字。

如果你期望得到精确的结果,请使用精确的数字类型。

对 NobbZ 的回答进行扩展:5.9902387 是最接近 5.9902389 的 32 位浮点数在十进制表示中的精确最小位数。顺带一提,我从提供的 playground 链接中看到打印出的结果是 5.9902387。我理解 NobbZ 的回答意味着他得到了 5.9902389。

image

不幸的是,对于这种情况,他链接的 FloatConverter 使用的是 float64,我没有看到 float32 的选项。无论如何,现在几乎所有人总是使用 float64。

如果你需要八位数的精度,只需使用 float64 而不是 float32,但也许你的例子是你实际问题的简化版本。更多的位数意味着更高的精度。如果你需要更高的精度,你将付出沉重的性能代价。根据你的使用场景,这可能是值得的。

在Go语言中,float32 到字符串的转换确实存在精度问题,因为 float32 本身是单精度浮点数,无法精确表示所有十进制小数。你遇到的 5.9902389 在转换为 float32 时,实际存储的值已经是 5.9902387,这是由单精度浮点数的二进制表示限制导致的。

如果你需要保留原始十进制字符串的精度,建议直接使用字符串处理,而不是通过 float32 类型。但如果你必须从 float32 转换并希望尽可能保留精度,可以使用 strconv.FormatFloat 并指定足够大的精度位数。对于 float32,通常 -1 参数会显示所有必要的小数位,但如上所述,二进制表示可能已经丢失了原始精度。

示例代码:

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var t float32
	t = 5.9902389
	// 使用足够大的精度位数,例如 9(float32 的十进制精度约为 6-9 位)
	numeroString := strconv.FormatFloat(float64(t), 'f', 9, 32)
	fmt.Println("Number float32:", t)
	fmt.Println("Number string:", numeroString)
}

输出:

Number float32: 5.9902387
Number string: 5.990238735

注意,即使指定了精度,输出仍然是 5.990238735 而不是 5.9902389,因为 float32 存储的值已经是近似值。

如果必须精确表示原始十进制数,考虑以下替代方案:

  1. 使用 float64(双精度)代替 float32,它提供更高的精度。
  2. 直接使用字符串类型存储原始数值,避免浮点数转换。
  3. 使用 decimal 类型库(如 shopspring/decimal)进行精确十进制运算。

示例使用 float64

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var t float64
	t = 5.9902389
	numeroString := strconv.FormatFloat(t, 'f', -1, 64)
	fmt.Println("Number float64:", t)
	fmt.Println("Number string:", numeroString)
}

输出:

Number float64: 5.9902389
Number string: 5.9902389

使用 float64 可以更精确地表示原始值,但注意浮点数仍有精度限制,并非所有十进制小数都能精确表示。

回到顶部