我System.Double最近询问过,并被告知计算可能因平台/架构而异.不幸的是,我找不到任何信息告诉我是否同样适用System.Decimal.
我是否保证在独立于平台/架构的情况下获得与任何特定计算完全相同的结果decimal?
Eri*_*ert 31
我是否保证在独立于平台/架构的情况下获得与任何特定十进制计算完全相同的结果?
在C#4规格显然,价值,你得到的将被计算在任何平台上是相同的.
正如LukeH的回答所指出的那样,ECMA版本的C#2规范赋予了符合实现的余地以提供更高的精度,因此在另一个平台上实现C#2.0可能会提供更高精度的答案.
出于这个答案的目的,我将只讨论C#4.0指定的行为.
C#4.0规范说:
对十进制类型值的操作结果是计算精确结果(保留每个运算符定义的比例)然后舍入以适合表示形式的结果.结果四舍五入到最接近的可表示值,并且当结果等于接近两个可表示的值时,结果四舍五入到在最低有效位数[...]中具有偶数的值.零结果始终具有0的符号和0的标度.
由于操作的精确值的计算在任何平台上应该是相同的,并且舍入算法是明确定义的,因此无论平台如何,结果值应该相同.
但是,请注意关于零的括号和最后一句.可能不清楚为什么这些信息是必要的.
十进制系统的一个奇怪之处在于,几乎每个数量都有多个可能的表示.考虑确切值123.456.十进制是96位整数,1位符号和8位指数的组合,表示从-28到28的数字.这意味着精确值123.456可以用小数123456 x 10 -3或1234560表示x 10 -4或12345600 x 10 -5.规模很重要.
C#规范还规定了如何计算有关比例的信息.文字123.456m将编码为123456 x 10 -3,而123.4560m将编码为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);
Run Code Online (Sandbox Code Playgroud)
这产生了
111.111000
111.111
222.222000
222.222
222.222000
True
True
True
Run Code Online (Sandbox Code Playgroud)
请注意如何在小数运算之间保留有关重要零数字的信息,并且decimal.ToString知道这一点并显示保留的零(如果可以).还要注意十进制相等如何知道基于精确值进行比较,即使这些值具有不同的二进制和字符串表示.
我认为规范实际上并不是说decimal.ToString()需要根据它们的比例正确地打印出带有尾随零的值,但如果没有这样做,那么实现就是愚蠢的.我会认为这是一个错误.
我还注意到CLR实现中十进制的内部存储器格式是128位,细分为:16个未使用位,8个标度位,7个未使用位,1个符号位和96个尾数位.内存中这些位的确切布局不是由规范定义的,如果另一个实现想要为了它自己的目的将额外的信息填充到这23个未使用的位中,它可以这样做.在CLR实现中,未使用的位应始终为零.
的decimal类型是在什么相当于使用结构与base-10表示的(含整数的,我相信),相对于double和其他浮点类型,其表示在基-2-非整数值.因此,decimals是在任何体系结构上的标准精度内的基数10值的精确表示.对于运行正确实现.NET规范的任何体系结构都是如此.
因此,为了回答您的问题,由于在decimal规范中以这种方式标准化了行为,因此在decimal符合该规范的任何体系结构上的值应该相同.如果他们不符合那个规范,那么他们就不是真正的.NET.
即使浮点类型的格式已明确定义,浮点计算确实可能具有不同的结果,具体取决于体系结构,如C#规范的4.1.6节所述:
可以以比操作的结果类型更高的精度执行浮点运算.例如,某些硬件体系结构支持"扩展"或"长双"浮点类型,其范围和精度比double类型更大,并使用此更高精度类型隐式执行所有浮点运算.只有在性能成本过高的情况下,才能使这种硬件架构以较低的精度执行浮点运算,而不是要求实现放弃性能和精度,C#允许更高精度的类型用于所有浮点运算.
虽然该decimal类型需要近似以使值在其有限范围内表示,但是根据定义,该范围被定义为适合于金融和货币计算.因此,它具有比float或更高的精度(和更小的范围)double.它也比其他浮点类型更明确定义,因此它看起来与平台无关(参见4.1.7节 - 我怀疑这种平台独立性更多是因为对于具有大小和类型的类型没有标准硬件支持精度decimal而不是因为类型本身,所以这可能会随着未来的规范和硬件架构而改变).
如果您需要知道该decimal类型的特定实现是否正确,您应该能够使用将测试正确性的规范来制作一些单元测试.
本说明书的阅读建议decimal-像float和double- 可能被允许在执行一些回旋余地,只要符合一定的最低标准.
以下是ECMA C#规范的一些摘录(第11.1.7节).所有大胆的重点都是我的.
该
decimal类型可以表示的值,包括那些在范围为1×10 -28至1×10 28与 至少 28个显著数字.类型的有限值集合
decimal的形式为(-1)s x c x 10 - e,其中符号s 为0或1,系数c由0 <= c < Cmax给出,标度e为使得额敏 <= Ë <= 的Emax,其中 的C max是至少 1×10 28,额敏 <= 0,和 的Emax > = 28.decimal类型不一定 支持有符号的零,无穷大或NaN的.为
decimals的绝对值小于1.0m,则该值是精确到至少 28 个小数位.对于decimal绝对值大于或等于的s1.0m,该值精确到至少 28位.
请注意,Microsoft C#规范(第4.1.7节)的措辞与ECMA规范的措辞明显不同.它似乎decimal更严格地锁定了更严重的行为.
| 归档时间: |
|
| 查看次数: |
2016 次 |
| 最近记录: |