C - 双精度求和

时间:2011-10-13 13:06:05

标签: c double precision

我对双重格式的精确度有疑问。


示例示例:

double K=0, L=0, M=0;
scanf("%lf %lf %lf", &K, &L, &M);
if((K+L) <= M) printf("Incorrect input");
else printf("Right, K=%f, L=%f, M=%f", K, L, M);

我的测试输入:

K = 0.1,L = 0.2,M = 0.3->条件但是转到'else'声明。


我如何纠正这种差异?还有其他方法可以求和吗?

3 个答案:

答案 0 :(得分:5)

在双精度IEEE 754二进制浮点格式(在英特尔和其他处理器上使用的格式)0.1 + 0.2 == 0.30000000000000004 :-)和0.30000000000000004 != 0.3的世界中(并注意到在奇妙的世界中{ {1}} s,0.1,0.2和0.3不存在“精确”数量。有一些非常靠近它们的双数,但如果你用完全精度打印它们,它们将不是0.1,0.2和0.3)

要笑一点,试试这个:http://pages.cs.wisc.edu/~rkennedy/exact-float

插入一个十进制数字并查看第二行和第三行,它显示数字在内存中的实际表示方式。它适用于Delphi,但doubleDouble对于Delphi和可能是所有C处理器的英特尔处理器都是相同的(在C中称为Singledouble < / p>

如果您想亲自尝试,请查看此http://ideone.com/WEL7h

float

输出:
3.00000000000000044409e-01
2.99999999999999988898e-01

(请注意,输出取决于编译器。根据选项,#include <stdio.h> int main() { double d1 = (0.1 + 0.2); double d2 = 0.3; printf("%.20e\n%.20e", d1, d2); return 0; } 可以编译并舍入为0.3)

答案 1 :(得分:1)

与整数值不同,浮点值的存储方式与为其赋值的方式完全不同。让我们考虑以下代码:

int i = 1; // this is and always will be 1
float j = 0.03 // this gets stored at least on my machine as something like 0.029999999

为什么会这样?那么在0.1和0.2之间的区间内存在多少个浮点数? 一个无限的数字!因此,有些值会按照您的意图存储,但会存储很多值,这些值将以较小的错误存储。

这就是为什么比较浮点值的平等不是一个好主意。尝试这样的事情:

float a = 0.3f;
float b = 0.301f;
float threshold = 1e-6;

if( abs(a-b) < threshold )
  return true;
else
  return false;

答案 2 :(得分:0)

任何两个不同的实数之间有无数的实数。如果我们能够代表其中的每一个,我们就需要无限的记忆。由于我们只有有限的内存,因此需要以有限的精度存储浮点数。达到该有限精度,可能不是0.1 + 0.2 <= 0.3。

现在,你真的应该阅读Paul R提供的优秀链接另一端的内容。