【问题标题】:What is the exact specification of Decimal arithmetic implementation for .NET?.NET 的十进制算术实现的确切规范是什么?
【发布时间】:2022-10-24 18:59:49
【问题描述】:

例如,

0.0000000000000000000000000001

表示为(lo mid hi 标志):

1 0 0 1c0000

当上面除以 10 时,结果是 (lo mid hi flags)

0 0 0 0

但是当它乘以 0.1M 时,结果是 (lo mid hi flags)

0 0 0 1c0000

换句话说,根据 Decimal,0.0000000000000000000000000001 乘以 0.1 就是 0.0000000000000000000000000000。但除以 10 为 0。

下面显示了不同的结果:

var o = 0.0000000000000000000000000001M;
Console.WriteLine($"{o * 0.1M}");
Console.WriteLine($"{o / 10M}");

我需要能够在虚拟机中复制这种行为和所有其他十进制算术。有人可以指出我的规格或解释理由吗? System.Decimal.cs 似乎没有提供见解。

更新:所以这似乎只是十进制乘法实现中的一个错误。操作员应保留比例(根据 IEEE 754 2008),但乘法不会。

【问题讨论】:

  • @Matthew Watson,这与问题无关
  • @Frank,我假设 new Decimal( 0, 0, 0, 0, 0 ) == new Decimal( 0, 0, 0, 0, 0x1C )?如果是这样,您似乎在询问 .NET 的特定实现/版本的内部细节。然而,您的问题中没有提到版本。 // 至于使用同一个值的不同表示的合理性?它可能只是使用在每种情况下最自然的那个。
  • @ikegami 在数字上它们是相等的,但是底层表示不同并且显示输出不同,这意味着程序行为不同,因此我不希望实现因版本而异。我将用一个例子来更新这个问题。
  • 回覆 ”但底层表示不同", 本身不相关。 // Re "显示输出不同,",但这是
  • @ikegami 是的,同意(见更新) - 请注意,对于十进制表示直接驱动显示输出等......

标签: c#


【解决方案1】:

language spec 说

对十进制类型的值进行运算的结果是计算精确结果(保留为每个运算符定义的比例)然后四舍五入以适应表示的结果。结果四舍五入到最接近的可表示值,并且当结果同样接近两个可表示值时,四舍五入到在最低有效数字位置具有偶数的值(这称为“银行家四舍五入”)。也就是说,结果至少精确到小数点后 28 位。请注意,舍入可能会从非零值产生零值。

Decimal 的精度为小数点后 28 位。您的示例中最接近的可表示值为零。

decimal d28 = 1e-28m; // 0.0000000000000000000000000001
d28 / 10

结果:0。

类实现可用here。数学运算符在辅助类(DecCalc) here 中实现。

link to multiplication

link to division

来自源(int[] bits 构造函数)的小注释,关于不同的表示(有效数字)在数字上是等效的

// Note that there are several possible binary representations for the
// same numeric value. For example, the value 1 can be represented as {1,
// 0, 0, 0} (integer value 1 with a scale factor of 0) and equally well as
// {1000, 0, 0, 0x30000} (integer value 1000 with a scale factor of 3).
// The possible binary representations of a particular value are all
// equally valid, and all are numerically equivalent.

【讨论】:

  • 如果我理解正确,这与问题无关。
  • 虽然我看到你的 deccalc 链接可能有助于回答它。谢谢。
  • 嗨@frank,也许我误解了这个问题。 “有人能指出我的规范吗”-> 提供了规范的链接。 “我需要能够复制这种行为和所有其他十进制算术”-> 提供数学实现的链接。也许你可以澄清你在问什么?
  • 是的,抱歉,也许我回复得太早了。我会看看那些链接。再次感谢。
  • @Frank:最后的评论似乎回答了你的问题......虽然它没有说明指定的内容,但它表明实际实现认为它们都是正确的结果,这意味着它不努力保证几个不同的任何算术运算都会产生相同值的编码。
猜你喜欢
  • 2015-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-10
  • 2010-09-18
  • 2012-02-19
  • 1970-01-01
相关资源
最近更新 更多