CLI 规范 Ecma 335 定义了三种浮点类型。Float32、float64 和 F。前两个是名义类型,第三个是表示类型,即 IL 中的“本机浮点”类型。
第 I.12.1.3 节,“浮点数据类型的处理”给出了理由:
浮点数(静态、数组元素和类的字段)的存储位置是固定大小的。支持的存储大小为 float32 和 float64。在其他任何地方(在评估堆栈上,作为参数、作为返回类型和作为局部变量)浮点数都使用内部浮点类型表示。在每个这样的实例中,变量或表达式的标称类型是 float32 或 float64,但其值可以在内部用额外的范围和/或精度表示。内部浮点表示的大小取决于实现,可以变化,并且应具有至少与所表示的变量或表达式一样大的精度。
这在当前的抖动实现中实际上并不存在,参数和局部变量实际上是 float32 或 float64。但它有一些先例,他们首先考虑这一点的可能原因是,英特尔处理器中的内部 FPU 寄存器是 80 位的。这是许多个月前英特尔设计 8087 协处理器时做出的设计决定。
这个想法在纸面上听起来非常好,它允许更精确地存储中间计算结果,以便计算的最终结果更准确。然而,毫无疑问,英特尔犯了十亿美元的错误,FPU 无法优化并且仍然允许一致的浮点结果。问题是内部 FPU 寄存器是有限的资源,只有 8 个。它也被实现为堆栈,处理起来很尴尬。如果涉及计算,则不可避免地需要将中间结果溢出到内存中。将 80 位值截断为 64 位。如果计算容易丢失很多有效数字,那么对代码的微小更改会在计算结果中产生很大差异。或者一般来说让程序员感到不安,因为第 16 位数字不是
好吧,这是一个大错误,也是 SO 大量问题的根源。当英特尔实现下一代浮点硬件时,这个想法被废弃了,XMM 和 YMM 寄存器是 64 位的。真正的寄存器,而不是堆栈。x64 抖动使用它们。让您的程序在 64 位模式下运行会产生与在 32 位模式下运行时不同的结果。还需要十年时间才能停止伤害。