为什么 C# System.Decimal(十进制)"waste" 位?
Why does C# System.Decimal (decimal) "waste" bits?
official docs中写的System.Decimal
的128位是这样填充的:
The return value is a four-element array of 32-bit signed integers.
The first, second, and third elements of the returned array contain
the low, middle, and high 32 bits of the 96-bit integer number.
The fourth element of the returned array contains the scale factor and
sign. It consists of the following parts:
Bits 0 to 15, the lower word, are unused and must be zero.
Bits 16 to 23 must contain an exponent between 0 and 28, which
indicates the power of 10 to divide the integer number.
Bits 24 to 30 are unused and must be zero.
Bit 31 contains the sign: 0 mean positive, and 1 means negative.
考虑到这一点,可以看出有些位是“浪费”或未使用的。
为什么不是例如 120 位整数、7 位指数和 1 位符号。
可能有一个很好的理由让小数成为现在的样子。这个问题想知道这个决定背后的原因。
这里是C# source of Decimal。注意 FCallAddSub
风格的方法。这些调用了这些方法的(不可用的)快速 C++ 实现。
我怀疑实现是这样的,因为这意味着在前 96 位中对 'numbers' 的操作可以简单快速,因为 CPUs 对 32 位字进行操作。如果使用 120 位,CPU 操作会更慢且更棘手,并且需要大量位掩码才能获得有趣的额外 24 位,这将很难使用。此外,这将 'pollute' 最高的 32 位标志,并使某些优化变得不可能。
如果你看一下代码,你就会发现这种简单的位布局在任何地方都很有用。毫无疑问,它在底层 C++(可能还有汇编程序)中特别有用。
基于 Kevin Gosse 的评论
For what it's worth, the decimal type seems to predate .net. The .net
framework CLR delegates the computations to the oleaut32 lib, and I
could find traces of the DECIMAL type as far back as Windows 95
我进一步搜索并在 oleauth32 Windows 95.
中找到了一个可能使用 DECIMAL 代码的用户
旧的 Visual Basic(非基于 .NET 的)和 VBA 有一种名为 'Variant' 的动态类型。在那里(而且只有在那里)你可以保存一些与我们当前的 System.Decimal
.
几乎相同的东西
Variant 始终为 128 位,前 16 位保留用于枚举值,其数据类型在 Variant 内。
其余 112 位的分离可能基于 90 年代初期的常见 CPU 架构或 Windows 程序员的易用性。不打包指数并在一个字节中签名只是为了让整数多一个字节可用,这听起来很明智。
构建 .NET 时,此类型的现有(低级)代码及其操作被重新用于 System.Decimal
。
这一切都没有得到 100% 的验证,我希望答案包含更多历史证据,但这就是我可以拼凑的。
official docs中写的System.Decimal
的128位是这样填充的:
The return value is a four-element array of 32-bit signed integers.
The first, second, and third elements of the returned array contain the low, middle, and high 32 bits of the 96-bit integer number.
The fourth element of the returned array contains the scale factor and sign. It consists of the following parts:
Bits 0 to 15, the lower word, are unused and must be zero.
Bits 16 to 23 must contain an exponent between 0 and 28, which indicates the power of 10 to divide the integer number.
Bits 24 to 30 are unused and must be zero.
Bit 31 contains the sign: 0 mean positive, and 1 means negative.
考虑到这一点,可以看出有些位是“浪费”或未使用的。
为什么不是例如 120 位整数、7 位指数和 1 位符号。
可能有一个很好的理由让小数成为现在的样子。这个问题想知道这个决定背后的原因。
这里是C# source of Decimal。注意 FCallAddSub
风格的方法。这些调用了这些方法的(不可用的)快速 C++ 实现。
我怀疑实现是这样的,因为这意味着在前 96 位中对 'numbers' 的操作可以简单快速,因为 CPUs 对 32 位字进行操作。如果使用 120 位,CPU 操作会更慢且更棘手,并且需要大量位掩码才能获得有趣的额外 24 位,这将很难使用。此外,这将 'pollute' 最高的 32 位标志,并使某些优化变得不可能。
如果你看一下代码,你就会发现这种简单的位布局在任何地方都很有用。毫无疑问,它在底层 C++(可能还有汇编程序)中特别有用。
基于 Kevin Gosse 的评论
For what it's worth, the decimal type seems to predate .net. The .net framework CLR delegates the computations to the oleaut32 lib, and I could find traces of the DECIMAL type as far back as Windows 95
我进一步搜索并在 oleauth32 Windows 95.
中找到了一个可能使用 DECIMAL 代码的用户旧的 Visual Basic(非基于 .NET 的)和 VBA 有一种名为 'Variant' 的动态类型。在那里(而且只有在那里)你可以保存一些与我们当前的 System.Decimal
.
Variant 始终为 128 位,前 16 位保留用于枚举值,其数据类型在 Variant 内。
其余 112 位的分离可能基于 90 年代初期的常见 CPU 架构或 Windows 程序员的易用性。不打包指数并在一个字节中签名只是为了让整数多一个字节可用,这听起来很明智。
构建 .NET 时,此类型的现有(低级)代码及其操作被重新用于 System.Decimal
。
这一切都没有得到 100% 的验证,我希望答案包含更多历史证据,但这就是我可以拼凑的。