2012-12-06 69 views
1

可能重复:
Why “for(i = 0.1 ; i != 1.0 ; i += 0.1)” doesn’t break at i = 1.0?双精度比较失败

我有一个数字(真实)区间[X,Y]。我必须使用类似遍历它:

nr = 0; 
for (i = x; i <= y; i += step) //step is a small double value 
    nr++; 

为[-1,1]与0.001的步骤,显然NR应为2001年(-1.000 0.999 ... 1.000),但它计算NR = 2000 (我调查过,最后一次比较失败:0.999 + 0.001> 1.000)

我该如何计算确切的nr值?

+3

'float' /'double'本质上是不精确的;如果您需要“确切”,请使用整数类型 – Kevin

+0

您真的只需要计算步数,还是会在循环体中有更多?它将会是什么? –

+0

nr表示映射到真实平面上的图像的高度。我计算for(s)中的一些像素值。我知道完全不可能计算nr,所以我会坚持“height =(int)((y - x)/ step)。 – kaspersky

回答

0
int nsteps = (int)((y-x)/step); 
for(int i=0; nsteps; ++i){ 
    double v = x + (i*step); // use v in your calculations 
} 
+1

我们应该考虑'x','y'和'step'的值,这可能会为'nsteps'产生一个不正确的值。 –

+0

这实际上是我现在使用的(尽力而为)解决方案。但是,它将计算nr = 2000。另外,在每次迭代中避免i *步进乘法不会更快吗? – kaspersky

+0

@ gg.kaspersky:在典型的处理器上,“i * step”并不昂贵,除非您正在处理一些动力不足的嵌入式处理器。 –

3

你需要使用整数来做到这一点,或者对不精确性感到满意,因为浮点数和双精度本质上不精确*。你的代码完全按照C语言规范工作。漂浮和双打在要求精确度的情况下不安全。

除此之外,您需要关于您的要求的更多信息。如果nr是一个温度,那么为了计算准确的数值,你需要使用物理或者不存在或者不能存在(我不是物理学家,所以我不能告诉你)。如果step实际上是一个非理性的价值,那么你必须四舍五入 - 你的电话和哪个是正确的取决于你的业务逻辑要求。如果它是合理的,并且不需要四舍五入,那么您需要乘以最小公分母,并使用s(或C中的分数类等)。

*根据注释花车/双打精确当分数有分母是2的幂,如果你能迫使stepy符合本您的问题将一种明白无误的,但当然,如果step不鸿沟均匀分配到y您需要执行与上述完全相同的业务逻辑处理。

+0

你会如何解决这个问题? – kaspersky

+0

我不知道,因为我不知道你的应用程序需求是什么。 – djechlin

+0

这既不回答问题,也不解释为什么代码不会按预期行事。 –

0

您遇到的问题是浮点数(floatdouble)没有完全存储,因此内存中的表示比不精确。

所以你有两个选择 - 用精确的数字生活,或者在循环周围使用整数,然后计算值。

这是可以做到如下:

int numberOfIntervals = 2000; 
double lowestValue = -1.0; 
for (loop = 0; loop <= numberOfIntervals; ++loop) 
{ 
    double v = (0.001 * loop) + lowestValue; 
} 
+0

在堆栈溢出中提出类似问题的许多情况下,循环显然有整数转换。但是,在这种情况下,x和y是任意的浮点值,并且如何实现所需的计算并不明显。这里实际上有一个有趣的问题,它不仅仅是一个简单的答案。 –

-1

它只是不正确的二进制浮点是不精确的。对于内容符合两个不同(正和/或负)幂的总和的数字,这个值是确切的。很明显,十进制数字符合十的幂次和,因此它们不会是精确的。基数为4,8和16,因为它们是2的倍数。

相当一段时间以前我发布了this answer,它会给你一个提示浮点数的确切程度。你也可以看到分数是如何通过求和两个负的幂来组合的。

至于如何解决问题,你有你需要的工具。如果算法不合适,可以使其适合。

+0

实际上,十进制数也符合两个幂的和:11 = 8 + 2 + 1,我们可以使用二进制编码它们的确切值,以及任何基础。差异不是int二进制/十进制基表示法,而是整数/实数。 – kaspersky

+0

因此,如果十进制数字也符合两个幂的原因,那么您的程序为何不工作? –

+0

我误解了你说的话(我的英文很差)。我以为你的意思是整数小数,但你的意思是分数。 – kaspersky