从 int64 转换为 float64 是否安全?

Dea*_*ean -1 go ieee-754

据我所知 int64 可以在 Go 中的 float64 中转换,语言允许使用float64(some_int64_variable),但我也知道并非所有 64 位有符号整数都可以用 double 表示(因为 IEE754 近似值)。

我们有一些代码可以使用美分接收商品的价格int64并执行类似的操作

const TB                    = 1 << 40

func ComputeSomething(numBytes int64) {
    Terabytes := float64(numBytes) / float64(TB)
Run Code Online (Sandbox Code Playgroud)

我想知道这有多安全,因为并非所有整数都可以用双精度表示。

ali*_*ias 6

回答“安全吗”确实需要更好地了解您的需求,以及您究竟如何处理这些数字。因此,让我们问一个相关但更精确的问题,我们可以肯定地回答:

不能精确表示的最小正整数值是多少float64

因为int64,这个数字原来是9007199254740993float64这是“跳过”的第一个整数。

这可能看起来相当大,而且也许并不那么令人震惊。(如果这些是“美分”,那么我相信大约是 90 万亿美元左右。)但是如果您使用单精度浮点数,答案可能会让您感到惊讶。如果您使用float32,则该数字为:16777217。如果按美分计算,约为 168,000 美元。幸好你没有使用单精度浮点数!

根据经验,您永远不应该使用float类型(无论其精度如何)来处理金钱。浮点数实际上并不是像离散量那样为“金钱”而设计的,而是处理科学应用中出现的小数值。舍入误差可能会逐渐增加,从而影响您的计算。请改用大整数表示形式。大整数实现可能会更慢,因为它们主要是在软件中实现的,但如果您正在处理金钱计算,我冒昧地猜测您并不真正需要硬件可以提供的浮点计算速度。


Eli*_*sky 5

取决于你所说的“安全”是什么意思。

是的,在某些情况下,这里可能会丢失精度。float64不能int64精确表示 的所有值(因为它只有 53 位尾数)。所以如果你需要一个完全准确的结果,这个函数并不“安全”;如果你想代表金钱,float64可能会遇到麻烦

另一方面,您真的需要绝对精确的 TB 数吗?将numBytes实际划分TB准确?这不太可能,但这完全取决于您的规格和需求。如果您的代码有一个字节计数器,并且您想显示大约有多少 TB(例如 0.05 TB 或 2.124 TB),那么这个计算就可以了。