为什么 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% 的验证,我希望答案包含更多历史证据,但这就是我可以拼凑的。