Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.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# 为什么是双舍入而十进制不是?_C#_Decimal - Fatal编程技术网

C# 为什么是双舍入而十进制不是?

C# 为什么是双舍入而十进制不是?,c#,decimal,C#,Decimal,以下C#代码: 输出 True False 显然,double和decimal都不能精确表示1/3。但是dbl*n四舍五入为1,而dec*n不是。为什么?这种行为记录在哪里 更新 请注意,我这里的主要问题是为什么他们的行为不同。假设在设计IEEE 754和.NET时,舍入的选择是有意识的选择,我想知道选择一种舍入而不是另一种舍入的原因是什么。在上面的示例中,double似乎能够更好地生成数学上正确的答案,尽管有效数字少于decimal。为什么decimal的创建者不使用相同的舍入?是否存在这样

以下C#代码:

输出

True
False
显然,
double
decimal
都不能精确表示1/3。但是
dbl*n
四舍五入为1,而
dec*n
不是。为什么?这种行为记录在哪里

更新

请注意,我这里的主要问题是为什么他们的行为不同。假设在设计IEEE 754和.NET时,舍入的选择是有意识的选择,我想知道选择一种舍入而不是另一种舍入的原因是什么。在上面的示例中,
double
似乎能够更好地生成数学上正确的答案,尽管有效数字少于
decimal
。为什么
decimal
的创建者不使用相同的舍入?是否存在这样的情况:十进制的现有行为更有利?

测试:

int n = 3;
double  dbl = 1d / n;
decimal dec = 1m / n;

Console.WriteLine("/n");
Console.WriteLine(dbl);
Console.WriteLine(dec);

Console.WriteLine("*n");
Console.WriteLine(dbl * n);
Console.WriteLine(dec * n);
结果:

/n
0.333333333333333
0.3333333333333333333333333333
*n
1
0.9999999999999999999999999999
十进制以10为基数保存,双精度和单精度以2为基数保存。 可能对于cpu中3*0.333之后的double,将出现二进制重载,结果为1。
但3*0.3--3以10为基数-无过载,结果0.9--9

double=>IEEE 754。。。decimal Expective=>假设decimal的N精度为1/3=0.333333。。。到N个地方。。所以0.3333…*3是0.9999。。。。在
控制台.WriteLine
行之前仍然有N个位置,那么
dec
的值是多少。这回答了问题的
dec
方面。对于问题的
dbl
方面,您需要什么文档?这与你对浮点数学的理解有什么不一致?请注意,
dbl
的行为当然不能保证-它在不同的CPU和运行时上可能会有不同的工作方式。@Sinatr:
decimal
不会“恢复自身”,这就是重点<代码>0.33…3*3==0.99…9。结果可以准确地表示出来。对于
double
,这种情况不会发生,因为相乘的分数比最终结果有更多的(二进制)数字,取整会使事情回到
1
。没有(整数)
n
会对
decimal
产生相同的结果,但是使用
0.3
@jeroemostert的
decimal n
可以达到相同的效果,正如您所说,decimal与double行为不同的原因不是它们使用不同类型的舍入,而是没有溢出触发舍入。结果精确地表示为十进制(0.33…3*3==0.99…9),而对于double则不是。我想这回答了我的问题。不。十进制的有效位实现为96位整数。它不使用二进制编码的十进制。将表示
333333..
的96位整数乘以
3
不符合结果,但
decimal
将其舍入,结果为
0.9999…
而非
1
。如果您的解释是正确的,那么
1m/0.3m*0.3m
也不应该以
1
结束(因为所有操作数都是可精确表示的),但它确实可以。@Jeroenmoster ok,如果尾数96位整数的原因可以是:1)指数基:浮点数为base-2,小数位数为base-10。(在源二进制整数中的移动点不同,或在将其转换为10进制数后不同)2)我们的0.3可以是二进制基数2中的周期性内容,可以产生反向效果。也可能不是以10为基数的二进制周期-就像11b*[10dec]^[-1b]。3) 也可以使效果标准化存储为双精度而非十进制。@JeroenMostert约1m/0.3m*0.3m。可能(只是可能):4a)1m/0.3m=>dec 3.33333--333=>表示所有3:[33--33d*10d^-27d]=>用于保存所有十进制3的长二进制96位:[10101000101010101b…*10d^-27d](这里不是实二进制,只是…)4b)对于乘法0.3,可能可以缩放为相同的27d,如[0300--00d*10d^-27d]=>[01…b*10d^-27]4c)对96位尾数的二进制进行运算后,尾数可能溢出并出现结果1。或者,当然,也许是别的什么。
/n
0.333333333333333
0.3333333333333333333333333333
*n
1
0.9999999999999999999999999999