2014-03-03 120 views
10

我正在爲我的應用程序開發單元測試,但我遇到了一個我不明白的奇怪問題。C++雙重比較的奇怪行爲

的代碼是:

double res = BytesTool::convertSize(1, BytesTool::Byte, BytesTool::KiloByte); 
double tmp = pow((double)1000, -1); 
QVERIFY(res == tmp); 

我從Linux計算機(主機64位)爲Linux 64位編譯與海灣合作委員會(主機64位)和交叉編譯的Windows 32位的Linux的mingw32的編譯器。

該程序工作正常(斷言成功)在調試和發佈模式下的Linux編譯。 對於Windows版本,它在調試版本中工作正常,但不適用於發行版;斷言失敗。

奇怪的部份是,如果我插入跟蹤,測試工作在Windows中:

double res = BytesTool::convertSize(1, BytesTool::Byte, BytesTool::KiloByte); 
printf("test"); 
double tmp = pow((double)1000, -1); 
QVERIFY(res == tmp); // Is TRUE when printf("test") is present, FALSE otherwise 

我迷路了,我真不明白髮生了什麼。爲什麼printf使它工作?

感謝您的幫助。

+1

你能發佈相關的asm代碼嗎? – Paranaix

+1

由於您使用的不是純C++的東西,因此很難理解您的代碼在做什麼。如何定義「BytesTool」和「QVERIFY」? –

+0

@Paranaix我同意你的想法,-O3正在優化一些步驟,但printf()恢復了行爲。 – JayInNyc

回答

6

printf將使它工作,因爲浮點數將從內部FPU 80位表示(假設x86「舊式」數學)轉換爲保存在double中的64位。

原因是當你調用另一個函數(同樣,假設x86老式的FPU調用約定)時,寄存器值必須移動到堆棧,這會導致它被舍入到64位精度。

您的其他彙編最有可能起作用,因爲它們使用SSE2 +數學,它具有本機64位浮點類型。

==測試浮點數是相同,這對浮點數幾乎從來都不是正確的。

在這種情況下,它不是因爲內部CPU表示不同於存儲在double中的表示。

當比較浮點數時,總是檢查它們是否足夠接近而不是相等。

#include <math.h> 

QVERIFY(fabs(res-tmp) < DBL_EPSILON) 
+0

非常感謝!這有助於發現問題。其實,我已經嘗試過使用DBL_EPSILON來完成一個功能,但是我卻沒有在所有情況下都能正常工作。這是因爲我宣佈它內聯。這是我認爲避免價值的登記移動,我沒有比較雙倍與相同的位大小。 – SaiyanRiku