对于我的项目,有必要将IEEE 754浮点类型“分解”为内部表示。我有以下类型:
type Sign =
| Positive
| Negative
type Number =
{ exponent: int32 // The exponent is de-biased when converting from floating-point types. Exponent values here range from −2,147,483,648 to 2,147,483,647.
mantissa: bigint } // There is no implicit leading 1 bit. If the original float was normal, the converting code prepends the originally hidden 1 bit to the mantissa. Subnormals do not have this bit prepended to the mantissa.
type Infinity = Infinity
type SuperFloat =
| Number of Sign * Number
| Infinity of Sign * Infinity
| NaN
这可以用一些语法快捷方式更好地编写以保存类型,或者这是我必须忍受的最小数量的类型来覆盖所有可能的浮动类型?
答案 0 :(得分:4)
首先,Infinity
类型并不真正有用:因为它只有一个值,所以它不会对任何信息进行编码。
然后,Sign
情况下你不需要Number
,因为数字本身有“烘焙”的标志 - 即尾数可以是负数(顺便说一句,因此你的表示是不仅仅是矫枉过正,而且实际上不正确)。
所以第二次迭代将是:
type Sign =
| Positive
| Negative
type Number = {
exponent: int32
mantissa: bigint }
type SuperFloat =
| Number of Number
| Infinity of Sign
| NaN
下一点是有争议的,取决于预期用途,但我个人会摆脱Sign
类型并用两个单独的案例编码无穷大符号:
type Number = {
exponent: int32
mantissa: bigint }
type SuperFloat =
| Number of Number
| PositiveInfinity
| NegativeInfinity
| NaN
最后,如果你愿意的话,你可以将指数和尾数直接带到DU下面,但是那个更有争议,甚至更多取决于用法:
type SuperFloat =
| Number of exponent: int32 * mantissa: bigint
| PositiveInfinity
| NegativeInfinity
| NaN
由于我在评论中提醒负零是一件事,所以我必须带回Sign
类型。无论如何它都在这里,我们也可以将它用于无限:
type Sign = Positive | Negative
type SuperFloat =
| Number of sign: Sign * exponent: int32 * mantissa: bigint
| Infinity of Sign
| NaN
然而,请注意此类型允许使用不正确的值,因为尾数仍可为负数。不幸的是,bigint
不能成为非负面的。
我认为将尾数设为bigint
是有原因的(你需要处理任意大数?),但如果没有具体原因,我建议改为使用uint64
代替。编码双精度浮点数就足够了。