C#双精度问题

7
想象一下,a - b < c(其中a、b、c是C#双精度浮点数)。是否可以保证 a < b + c
谢谢!
编辑 假设不会发生算术溢出,就像以下示例:
double a = 1L << 53;
double b = 1;
double c = a;

Console.WriteLine(a - b < c); // Prints True
Console.WriteLine(a < b + c); // Prints False

假设 Math.Abs(a) < 1.0 && Math.Abs(b) < 1.0 && Math.Abs(c) < 1.0

这与C#或任何特定的数据类型(甚至编程)有什么关系?在我看来,这似乎是纯数学。 - Fredrik Mörk
2
@Fredrik Mörk:不,这完全是关于精度的。 - jgauffin
1
@Fredrik Mörk:因为这与语言在非整数算术方面的精度水平有关。 - BeRecursive
@jgauffin和@BeRecursive:当然没问题! :) - Fredrik Mörk
实际上,这个数学问题相当简单,它与数据类型有关。想象一下像 3.0 * (1.0/3.0) == 1.0 这样的事情等于 1.0 等等。在数学上是正确的,在 C# 中可能不会完全保持,这取决于数据类型。 - Tomas Vana
3个回答

14
不行。假设a = c,其中a是一个非常大的数,而b是一个非常小的数。可能会出现a - b具有比a更小的表示形式,但a + b非常接近a(且更大),以至于它最终仍然以最精确地表示为a。
下面是一个例子:
double a = 1L << 53;
double b = 1;
double c = a;

Console.WriteLine(a - b < c); // Prints True
Console.WriteLine(a < b + c); // Prints False

编辑:

这里有另一个例子,与您编辑后的问题相匹配:

double a = 1.0;
double b = 1.0 / (1L << 53);
double c = a;

Console.WriteLine(a - b < c); // Prints True
Console.WriteLine(a < b + c); // Prints False
换句话说,当我们从1中减去一个非常小的数时,我们得到的结果比1小。当我们给1加上同样的数字时,由于双精度的限制,我们只会得到1。

或者另一种方式,我也有这样的感觉。 - Tomas Vana
2
a=c=double.MaxValue 时,情况变得更加奇怪。然后两者都是 false。 - Vilx-
很好的例子,确实如此。但实际上我们处理的是微小数字,而不是接近double.MaxValue的值。请阅读编辑部分获取更多信息。 - levanovd
@levanovd:1 << 53比double.MaxValue要小得多。这里没有发生溢出。 - Jon Skeet
@levanovd:我提供了另一个符合您限制条件的示例。 - Jon Skeet

6
不总是如此:
        double a = double.MaxValue;
        double b = double.MaxValue;
        double c = 0.1;
        Console.WriteLine(a - b < c); // True
        Console.WriteLine(a < b + c); // False

2

这个链接讲述了浮点运算的属性,可能非常有趣:

浮点数谬误

特别是搜索关系的属性


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接