2011-08-12 214 views
1

为什么在下面的代码中打印这个文件从不打印?我已经认识到shiftx和shifty以确保在某些时候它们都是0.3。C++循环打印

for(double shifty=0; shifty < 2; shifty+=.1) { 
    for(double shiftx=0; shiftx < 2; shiftx +=.1) { 
     if((shiftx == 0.3) && (shifty == 0.3)) { 
      cout << "PRINT THIS" << endl; 
     } 
    }  
} 

回答

9

黄金法则是:避免在浮点平等测试。

0.1和0.3都不能精确表示。

标准阅读:What Every Computer Scientist Should Know About Floating-Point Arithmetic

要解决您的特定问题,您应该使用整数类型进行迭代和执行比较。只有在实际需要时才转换为浮点类型。例如:

for(int shifty=0; shifty < 20; shifty++) { 
    for(int shiftx=0; shiftx < 20; shiftx++) { 
     double shifty_double = shifty * 0.1; 
     double shiftx_double = shiftx * 0.1; 
     if((shiftx == 3) && (shifty == 3)) { 
      cout << "PRINT THIS" << endl; 
     } 
    }  
} 
+0

我明白为什么这个工程,但如果0.3不能正确代表,你尝试用.3比3,不会他们都不能正确代表,因此比较等于?还是说它们可以以几乎不同的方式“几乎”表现出来,而这只是让它们平等或不平等的机会? –

+1

@Seth或多或少总结它。它们可以以几乎不同的方式“表示”,文字值.1和.3将转换为编译器选择的近似浮点形式,无论.1的浮点形式如何,如果它并不是0.3近似值的1/3,那么内部循环中的相等性测试将失败。 – csj

4

这可能是由于使用双精度时的舍入误差,因为0.3在内部实际上并未实际存储为0.3。

比较双打的一种方式是允许比较中出现一些错误。 例

if(abs(shiftx - shifty) < 0.000001)