c#编译器如何以不同的方式处理加法和乘法

c#编译器如何以不同的方式处理加法和乘法,c#,types,C#,Types,因为c#中的浮点数/双精度数只有在基2中才能精确表示;我希望t2和t3都不是零,但是t2=0,而t3确实不是零。有人能解释一下吗 double d2 = 1.0/3.0; double t2 = 1.0 - 3.0*d2; double t3 = 1.0 - d2 - d2 - d2; 在t2的情况下,您创建了几个中间值,这些中间值确实会导致一定程度的错误。碰巧的是,这些操作会产生相等和相反的误差量,导致这些误差恰好抵消为零的净误差,并产生正确的结果 t3的情况导致每个中间操作的错误相等而不是

因为c#中的浮点数/双精度数只有在基2中才能精确表示;我希望
t2
t3
都不是零,但是
t2=0
,而t3确实不是零。有人能解释一下吗

double d2 = 1.0/3.0;
double t2 = 1.0 - 3.0*d2;
double t3 = 1.0 - d2 - d2 - d2;

t2
的情况下,您创建了几个中间值,这些中间值确实会导致一定程度的错误。碰巧的是,这些操作会产生相等和相反的误差量,导致这些误差恰好抵消为零的净误差,并产生正确的结果


t3
的情况导致每个中间操作的错误相等而不是相反,导致错误相互混合,而不是相互抵消,导致净非零错误。

我认为问题不在于C#it本身,而在于微处理器的工作方式。您不能将1/3除以,然后期望一个数字存储为1/3

计算机还通过一些技巧(添加错误)来理解普通数学:

double d1 = 1/3.0;
d1 = d1 * 3.0;
将导致

 d1 = 1.0

您没有解释为什么
d1*3.0
等于
1
。正是因为浮点数不能准确地表示
1/3
,所以您没有任何特别的理由实际期望
1
的结果。非常感谢您的快速回答!刚刚测试过,我认为你是绝对正确的,就好像我做了
1.0-2.0*d2-d2
那么不是0证明了你的观点(至少在某种程度上)。那么这个错误消除是随机的吗?我模模糊糊地记得有人在某处读到这样一句话:微软有意地“取消”了这个结果,至少在大多数情况下,它的工作原理和普通代数一样。它是任意的,但不是随机的。每次执行操作时都会得到相同的结果(这是确定性的),但这不是设计的结果。在一般情况下,您不能依赖这样一个事实,即除以一个数字,然后再乘以相同的数字将得到原始值。你可以期望它们在一定的误差范围内;在这种情况下,误差恰好为0,但在一般情况下,误差在一定范围内。