Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Is.NET“;十进制”;算法独立于平台/架构?_C#_.net_Math - Fatal编程技术网

C# Is.NET“;十进制”;算法独立于平台/架构?

C# Is.NET“;十进制”;算法独立于平台/架构?,c#,.net,math,C#,.net,Math,我最近询问了有关System.Double的问题,他们告诉我,计算可能会因平台/架构的不同而有所不同。不幸的是,我找不到任何信息来告诉我这是否适用于System.Decimal 对于任何特定的decimal计算,我能保证得到与平台/架构完全相同的结果吗?与double和其他浮点类型相反,decimal类型是使用结构(我相信包含整数)以10为基数表示的,表示基-2中的非整数值。因此,decimals是任何体系结构上以标准化精度表示的精确的10进制值。对于任何运行正确的.NET规范实现的体系结构来说

我最近询问了有关System.Double的问题,他们告诉我,计算可能会因平台/架构的不同而有所不同。不幸的是,我找不到任何信息来告诉我这是否适用于
System.Decimal


对于任何特定的
decimal
计算,我能保证得到与平台/架构完全相同的结果吗?

double
和其他浮点类型相反,
decimal
类型是使用结构(我相信包含整数)以10为基数表示的,表示基-2中的非整数值。因此,
decimal
s是任何体系结构上以标准化精度表示的精确的10进制值。对于任何运行正确的.NET规范实现的体系结构来说都是如此

所以为了回答您的问题,由于规范中的
decimal
行为是以这种方式标准化的,
decimal
值在符合该规范的任何体系结构上都应该是相同的。如果它们不符合该规范,那么它们就不是真正的.NET


尽管浮点类型的格式已明确定义,但根据体系结构的不同,浮点计算可能会产生不同的结果,如中所述:

浮点操作可能是 执行精度高于 操作的结果类型。对于 例如,一些硬件架构 支持“扩展”或“长双精度” 具有更大范围的浮点类型 与双精度型相比, 并隐式执行所有 使用此 更高精度的类型。只在 性能成本过高可能会导致这种情况 硬件体系结构可用于 使用 精度较低,而不是 要求执行没收 性能和精度,C# 允许使用更高精度的类型 用于所有浮点运算 行动

虽然
decimal
类型需要近似值才能在其有限范围内表示值,但根据定义,该范围适用于金融和货币计算。因此,它比
float
double
具有更高的精度(和更小的范围)。它的定义也比其他浮点类型更清晰,因此它看起来与平台无关(-我怀疑这种平台独立性更多是因为没有标准硬件支持大小和精度为
decimal
的类型,而不是因为类型本身,因此这可能会随着未来的规范和硬件架构而改变)


如果您需要知道
decimal
类型的特定实现是否正确,那么您应该能够使用将测试正确性的规范来设计一些单元测试。

对规范的阅读表明
decimal
——比如
float
double
——可能会被允许一些级别只要符合一定的最低标准,在其实施过程中应始终遵守

以下是从(第11.1.7节)中摘录的一些内容。所有粗体部分都是我的


decimal
类型可以表示值,包括 范围为1 x 10−28至1 x 1028,带 至少28位有效数字

decimal
类型的有限值集的形式如下 (-1)s x c x 10-e,其中符号s 为0或1时,系数c由0给出 对于任何特定的十进制计算,独立于平台/体系结构,我是否保证得到完全相同的结果

C#4规范清楚地表明,您得到的值在任何平台上的计算结果都是相同的

正如LukeH的回答所指出的,ECMA版本的C#2规范为一致性实现提供了更高精度的余地,因此在另一个平台上实现C#2.0可能会提供更高精度的答案

为了回答这个问题,我将只讨论C#4.0指定的行为

C#4.0规范规定:


对decimal类型的值进行运算的结果是计算精确结果的结果(保留为每个运算符定义的比例)然后四舍五入以适应表示。结果四舍五入到最接近的表示值,当结果与两个表示值相等时,四舍五入到在最低有效位[…]处有偶数的值。零结果始终具有0的符号和0的刻度


由于运算的精确值在任何平台上的计算都应相同,并且舍入算法定义良好,因此无论平台如何,结果值都应相同

然而,请注意括号和最后一句关于零的句子。可能不清楚为什么需要这些信息

十进制中的一个奇怪之处是几乎每一个数都有不止一个可能的表示。考虑精确值123.456。小数是96位整数、1位符号和八位指数的组合,它代表从28到28的数。这意味着精确值123.456可以用小数表示。123456 x 10-3或1234560 x 10-4或12345600 x 10-5。比例问题。

C#规范还要求如何计算有关刻度的信息。文字123.456m将编码为123456 x 10-3,123.456m将编码为1234560 x 10-4

观察此功能的作用效果:

decimal d1 = 111.111000m;
decimal d2 = 111.111m;
decimal d3 = d1 + d1;
decimal d4 = d2 + d2;
decimal d5 = d1 + d2;
Console.WriteLine(d1);
Console.WriteLine(d2);
Console.WriteLine(d3);
Console.WriteLine(d4);
Console.WriteLine(d5);
Console.WriteLine(d3 == d4);
Console.WriteLine(d4 == d5);
Console.WriteLine(d5 == d3);
这就产生了

111.111000
111.111
222.222000
222.222
222.222000
True
True
True
请注意,关于有效零位数的信息是如何在对小数的操作中保留的,并且decimal.ToString知道有关零位数的信息