簡體   English   中英

在c ++中奇怪的雙重轉換行為

[英]strange double to int conversion behavior in c++

以下程序顯示了我在c ++中看到的奇怪的double to int轉換行為:

#include <stdlib.h>
#include <stdio.h>

int main() {
  double d = 33222.221;
  printf("d = %9.9g\n",d);

  d *= 1000;
  int i = (int)d;

  printf("d = %9.9g | i = %d\n",d,i);

  return 0;
}

當我編譯並運行程序時,我看到:

g++ test.cpp
./a.out
d = 33222.221
d =  33222221 | i = 33222220

為什么我不等於33222221? 編譯器版本是GCC 4.3.0

浮點表示幾乎從不精確(僅在特殊情況下)。 每個程序員都應該讀到: 每個計算機科學家應該知道的關於浮點運算的內容

簡而言之 - 您的號碼可能是33222220.9999999999999999999999999999999999999999999999999999999999999999998(或類似的東西),截斷后變為33222220。

當你附加一個調試器,檢查值,你會看到的價值d實際上是33222220.999999996 ,當轉換為整數,這是正確截斷為33222220。

可以存儲在雙變量中的數量有限,而33222221不是其中之一。

由於浮點近似,33222.221實際上可能是33222.220999999999999。 乘以1000得出33222220.999999999999。 強制轉換為整數會忽略所有小數(向下舍入),最終結果為33222220。

如果將printf()調用中的“9.9g”更改為17.17以使用64位IEEE 754 FP編號恢復所有可能的精度數字,則獲得雙精度值33222220.999999996。 然后int轉換是有道理的。

我不想重復其他評論的解釋。

所以,這里只是一個建議,以避免像所描述的問題:

  1. 盡可能避免浮點算法(特別是涉及計算時)。

  2. 如果確實需要浮點算術,那么一定不能通過operator ==比較數字! 使用你自己的比較函數(或使用一些庫提供的函數),使用某種epsilon比較(絕對或相對於數字的magniture)做類似“幾乎相等”的比較。

例如,參見優秀的文章

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

由布魯斯道森代替!

斯特凡

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM