我遇到了以下算术问题。
但是结果和正常的数学运算不同,为什么会这样呢?
double d1 = 1.000001;
double d2 = 0.000001;
Console.WriteLine((d1-d2)==1.0);
我遇到了以下算术问题。
但是结果和正常的数学运算不同,为什么会这样呢?
double d1 = 1.000001;
double d2 = 0.000001;
Console.WriteLine((d1-d2)==1.0);
我想你在 Jon Skeet 的 Brainteasers 页面上找到了这个问题?答案在同一网站上列出和解释。
作为参考,这是从该页面复制的答案。
3)愚蠢的算术
计算机应该擅长算术,不是吗?为什么这会打印“False”?
double d1 = 1.000001; double d2 =
0.000001; Console.WriteLine((d1-d2)==1.0);
答:这里的所有值都存储为二进制浮点数。采用虽然1.00001实际上存储在1.00001实际上存储为1.00000099999999322998046695600470493236333362046936/30801,00017333362046956/303033339303936/3099999999981deraiver] hys,而1.000001实际上是1.000001的实际存储为1.00000099999999322998046932999804695633362046956004798936633398049366/3080807366455078 它们之间的差值不完全是 1.0,实际上也不能准确地存储差值。
从Double.Equals的 MSDN 条目中:
比较精度
应谨慎使用 Equals 方法,因为由于两个值的精度不同,两个明显等效的值可能不相等。下面的示例报告 Double 值 .3333 和通过将 1 除以 3 返回的 Double 不相等。
...
一种推荐的技术不是比较相等性,而是定义两个值之间的可接受差异范围(例如其中一个值的 0.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 equal to 0?
这是因为计算机以 2 为底进行数学运算,因此许多十进制浮点数不能用有限的位数精确表示。
如果您在应用程序中执行此类算术,decimal
则应使用该类型
decimal d1 = 1.000001M;
decimal d2 = 0.000001M;
Console.WriteLine((d1 - d2) == 1.0M); // evaluates as true
这可能是由于浮点精度问题,因为您的结果可能不完全是 1.0,但可能类似于 1.000000000001
发生这种情况是因为浮点类型使用以 2 为基数而不是以 10 为基数的表示存储数字。这导致 double 无法准确存储像 0.1 这样的值。例如 0.1 由单个值 0.100000001490116119384765625 表示。
您必须使用 Decimal 来消除错误。
看看 python 文档必须说这两个问题是一样的: