2016-10-18 30 views
0

我正在進行計算,它將double轉換爲binary,在此過程中發生了一個奇怪的問題,最終導致錯誤。因此,當我發現結果錯誤時,我會打印出小數部分。在計算double值時錯誤計數增加

一塊爲小數部分的代碼是這樣的:

 while(float_part != (int)(float_part)){ 
      float_part -= (int)(float_part); //just leave fractional part 
      float_part *= 2; //float_part is a double 
      res = res + to_string(((int)(float_part))); //add to "res", which is a string 
      cout << float_part << "+" << length << "\n"; //to figure out why 
      length--; //the length is initialized to 32 
      if(length <= 0){ 
       return "ERROR"; //if too long 
      } 
    } 

然後我輸入「28187281.525」(僅0.525在上面的代碼段的事項),並發現其結果是如此奇怪:

1.05+32 
    0.1+31 
    0.2+30 
    0.4+29 
    0.8+28 
    1.6+27 
    1.2+26 
    0.4+25 
    0.799999+24 
    1.6+23 
    1.2+22 
    0.399994+21 
    0.799988+20 
    1.59998+19 
    1.19995+18 
    0.399902+17 
    0.799805+16 
    1.59961+15 
    1.19922+14 
    0.398438+13 
    0.796875+12 
    1.59375+11 
    1.1875+10 
    0.375+9 
    0.75+8 
    1.5+7 
    1+6 
    1101011100001101010010001.100001100110011001100110011 

一開始沒關係,但最終結果出錯了!

爲什麼0.4 * 2成爲0.799999 ..

任何人都知道的原因是什麼?提前致謝!

+0

這麼多重複已經 –

+0

好吧..謝謝你們 –

回答

2

浮點值的精度有限。您對它們執行的任何操作都可能導致小錯誤。您執行的操作越多,錯誤就越多。在你的情況下,你應該將你的浮點變量分解爲整數部分(符號,尾數和指數),並對這些整數執行任何操作。浮動點通常存儲在IEEE_754格式:

https://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers

+0

所以基本上,將小數部分轉換爲int或long是唯一安全的方法?還有其他的技巧嗎? –

+0

訣竅是將浮點值複製到適當大小的「int」中(您可以對此或直接使用'memcpy()')使用'union',然後使用按位運算並移位以獲得符號位,指數和尾數。一旦你完成了這些,事情應該是非常簡單的,因爲基本上你只是以二進制打印尾數,剩下的唯一問題就是把小數點放在正確的位置。 –

+0

謝謝,我按照這種方式看起來不錯! –

1

這是有限的精度運算的,當你操縱,不能精確表示值的性質。

0.4 * 2由於同樣原因變成0.7999999 1/3變爲0.9999999 - 你可以用小數做的最好代表1/3代表0.333333,如果你乘以3得到0.99999。您需要無限數量的數字才能得到確切的答案。

+0

嘿,謝謝你,所以幾乎如何計算浮動或雙?將小數部分轉換爲int還是long?這似乎很麻煩.. –

+0

這確實取決於你想要做什麼。但是,也許你正在使用錯誤的工具來完成這項工作,並且應該使用其他的東西。對於分數,可能是整數的比率。對於浮點,也許更高的精度,也許舍入,也許浮點小數點。這取決於你的要求是什麼。但是,您不能跳過確定需求並選擇可以滿足需求的工具的步驟。 –