为什么Golang中NaN的uint64和MaxFloat64相等?

Why Is uint64 of NaN and MaxFloat64 equal in Golang?

以下条件的计算结果为 true,寻找有关原因的解释 -

x, y := math.NaN(), math.MaxFloat64 

fmt.Println(uint64(x) == uint64(y))

>>> true

具体来说,为什么 uint64(math.NaN()) = 9223372036854775808

语言 运行 次通常不会注意如果您尝试将 NaN 值转换为整数会发生什么。他们通常只是发出相应的硬件指令,让“硬件”做它做的事。

所以,问题是硬件在这种情况下做了什么?当然,这取决于您的特定 machine/ISA 是什么。假设最常见的 Intel x86 架构,使用的相应指令很可能是 CVTTSD2SI,但您应该检查程序生成的程序集以确保确实如此。以下是有关此指令行为的相关引述:

If a converted result exceeds the range limits of signed quadword integer (in 64-bit mode and REX.W/VEX.W/EVEX.W = 1), the floating-point invalid exception is raised, and if this exception is masked, the indefinite integer value (80000000_00000000H) is returned.

基于此,正在发生的事情是处理器引发了无效异常,默认情况下它被大多数语言屏蔽 运行 次,因此您的程序只是继续运行。因此,您将获得指令指定的值 0x8000000000000000,相当于十进制的 9223372036854775808,解释您观察到的结果。

如果您担心这些转换,您应该在进行转换之前检查有效范围,或者取消屏蔽异常并让您的程序获得浮点异常。当然,您应该仔细考虑是否值得进行额外检查,因为这会影响性能。揭露异常虽然在道德上是“正确”的事情,但也是有问题的,因为您不希望您的“number-c运行ching”程序在 运行 时崩溃。显然,正确的做法取决于您的 circumstances/needs 是什么。

注:

这是您的程序在 x86 上的汇编输出:https://go.godbolt.org/z/YfqKdvY6E You can see the call to cvttsd2si on line 100 and others. Here's a simpler program that compiles to a shorter assembly, whose output is easier to read, and showing the use of cvtsd2si more prominently on line 14: https://go.godbolt.org/z/r7Pq5Tqqh