我遇到了以下算术问题。
但结果与正常的数学运算不同,为什么会这样呢?
double d1 = 1.000001;
double d2 = 0.000001;
Console.WriteLine((d1-d2)==1.0);
答案 0 :(得分:14)
我认为你在Jon Skeet的Brainteasers页面上找到了这个问题?答案在同一网站上列出并解释here。
作为参考,这是从该页面复制的答案。
3)愚蠢算术
计算机应该擅长算术,不是吗?为什么打印“假”?
double d1 = 1.000001; double d2 =
0.000001; Console.WriteLine((d1-d2)==1.0);
答案:此处的所有值都存储为二进制浮点数。虽然1.0可以准确存储,但实际存储的是1.000001 1.0000009999999999177333620536956004798412322998046875,并且0.000001实际存储为 0.000000999999999999999954748111825886258685613938723690807819366455078125。它们之间的差异并不完全是1.0,实际上差异也不能完全存储。
答案 1 :(得分:3)
来自Double.Equals的MSDN条目:
比较精确度
Equals方法应该与。一起使用 谨慎,因为两个显然 等值可能是不等的 两者的精度不同 值。以下示例报告 那个Double值.3333和 通过除以1而得到的双是 不相等的。
...
而不是比较平等, 一种推荐的技术涉及 定义可接受的边际 两个值之间的差异(例如 其中一个值的.01%)。如果 差异的绝对值 两个值之间小于或 等于那个边际,差异 可能是由于差异造成的 精度,因此,价值 可能是平等的。下列 示例使用此技术进行比较 .33333和1/3,两个Double值 上一个代码示例找到了 不平等。
如果你需要进行大量的“相等”比较,那么在.NET 3.5中编写一个小帮助函数或扩展方法进行比较可能是一个好主意:
public static bool AlmostEquals(this double double1, double double2, double precision)
{
return (Math.Abs(double1 - double2) <= precision);
}
这可以通过以下方式使用:
double d1 = 1.000001;
double d2 = 0.000001;
bool equals = (d1 - d2).AlmostEquals(1.0, 0.0000001);
看到这个非常相似的问题:C#.NET: Is it safe to check floating point values for equality to 0?
答案 2 :(得分:2)
这是因为计算机在基数2中进行数学运算,因此许多十进制浮点数不能用有限的位数精确表示。
答案 3 :(得分:2)
答案 4 :(得分:2)
如果您在应用程序中进行此类算术运算,则应使用decimal
类型
decimal d1 = 1.000001M;
decimal d2 = 0.000001M;
Console.WriteLine((d1 - d2) == 1.0M); // evaluates as true
答案 5 :(得分:1)
这可能是由于浮点精度问题,因为可能你的结果不是1.0,但可能是1.000000000001
答案 6 :(得分:1)
这是因为浮点类型使用基数2而不是基数十表示来存储数字。这导致double无法精确存储0.1之类的值。例如,0.1由单个值0.100000001490116119384765625表示。
你必须使用Decimal来消除错误。
答案 7 :(得分:1)
答案 8 :(得分:0)
看看python docs有什么说法,两个问题都是一样的: