.net CLR中本机浮点类型的用法

.net CLR中本机浮点类型的用法,.net,cil,.net,Cil,我发现CIL编译器允许类型本机浮点。但是,CLR不允许这样做。它有什么用处吗?它有多大?是否有相应的.NET类型?我尝试将其实现为伪基元类型: .class public sequential ansi serializable sealed beforefieldinit NativeFloat extends System.ValueType { .field assembly native float m_value } 但是,CLR不支持此类型。谢谢你的帮助 编辑:如果已安装,

我发现CIL编译器允许类型
本机浮点
。但是,CLR不允许这样做。它有什么用处吗?它有多大?是否有相应的.NET类型?我尝试将其实现为伪基元类型:

.class public sequential ansi serializable sealed beforefieldinit NativeFloat
  extends System.ValueType
{
  .field assembly native float m_value
}
但是,CLR不支持此类型。谢谢你的帮助

编辑:如果已安装,则其CorElementType为26(0x1a,R)。

来自CIL ECMA规范:

本机大小类型(本机int、本机unsigned int、O和&)为 CLI中用于延迟选择值大小的机制。 这些数据类型作为CIL类型存在;但是,CLI将每个映射到 特定处理器的本机大小。(例如,数据类型I 在奔腾处理器上映射到int32,但在IA64上映射到int64 因此,大小的选择将推迟到JIT编译 或运行时,当CLI已初始化且体系结构 知道。这意味着字段和堆栈帧偏移也不相同 在编译时已知

现在,说到这里,
本机浮点
(与
本机int
)在ECMA规范中一次也没有提到。我能找到的唯一证据是在一些开源CIL汇编程序中,它们抛出异常,声明它们无法为
本机浮点
生成操作码

如果微软的CIL编译器确实接受这种类型,我可以想象这是微软打算实现的功能,但最终并没有将其放入MSIL(CIL的前身)中。此外,如果汇编程序确实生成了一个操作码而不是错误消息,我可以想象(尽管这也是推测),可能存在支持该操作码的Microsoft CLR变体(可能是.NET Micro Framework或Silverlight的某个特定版本,或其他什么)

还要注意,在上面的规范中提到了CLI。CLR仅仅是Microsoft对CLI的实现

ECMA规范确实提到了本机浮点类型,但它不是本机浮点类型

F、 浮点值(float32、float64或其他表示形式 由底层硬件支持)


CLI规范Ecma 335定义了三种浮点类型。Float32、float64和F。前两个是标称类型,第三个是表示类型,即IL中的“本机float”类型

第I.12.1.3节“浮点数据类型的处理”给出了基本原理:

浮点数(静态、数组元素和类字段)的存储位置大小固定。支持的存储大小为float32和float64。在其他任何地方(在计算堆栈上,作为参数、返回类型和局部变量),浮点数都使用内部浮点数类型表示。在每个这样的实例中,变量或表达式的标称类型为float32或float64,但其值可以用额外的范围和/或精度在内部表示。内部浮点表示的大小取决于实现,可以变化,并且其精度至少应与所表示的变量或表达式的精度相同

这在当前的抖动实现中并不存在,参数和局部变量实际上是float32或float64。但这有一些先例,他们首先考虑这一点的可能原因是,英特尔处理器中的内部FPU寄存器是80位。这是许多月前英特尔设计8087协处理器时做出的设计决定

这个想法在纸面上听起来很好,它允许以更高的精度存储中间计算结果,从而使计算的最终结果更准确。然而,毫无疑问,这是英特尔数十亿美元的错误,FPU不可能优化,并且仍然允许一致的浮点结果。问题在于内部FPU寄存器是有限的资源,只有8个。它也被实现为一个堆栈,处理起来非常笨拙。如果涉及到计算,则不可避免地需要将中间结果泄漏到内存中。将80位值截断为64位。如果计算容易丢失大量有效数字,则对代码的微小更改会在计算结果中产生较大差异。或者一般来说,程序员会因为第16位数字不一样而感到不安


嗯,这是一个很大的错误,也是目前大量问题的根源。当英特尔实施下一代浮点硬件时,这个想法被放弃了,XMM和YMM寄存器是64位的。真寄存器,而不是堆栈。x64抖动使用它们。使程序在64位模式下运行会产生与在32位模式下运行时不同的结果。这将需要十年的时间才能停止伤害。

这是一个非常可怕的问题,值得CIL大师们更多关注。