2017-08-27 22 views
3
#include <iostream> 
#include <limits> 

int main() 
{ 
    double d = std::numeric_limits<double>::max(); 
    std::cout << std::to_string(d) << std::endl; 
    std::cout << std::to_string(d - 1) << std::endl; 
} 
 
[[email protected]_host ~]$ g++ test.cpp 
[[email protected]_host ~]$ ./a.out 
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 

1。減去爲什麼沒有第二一端與7?爲什麼不能從最大雙

+3

您需要了解浮點表示。他們對最後一位數字不準確。我相信維基百科有一個很好的開始。 –

+2

這肯定是重複的。 – Puppy

+0

閱讀http://浮點gui。de /(並記住該URL) –

回答

2

C++中的double是最常見的符合binary64格式的IEE 754.所以我們將基於這個答案。它也適用於其他浮點格式,例如float(binary32),binary16,它沒有本機C++類型,甚至非IEEE 754浮點格式。你的雙精度是52位尾數和11指數組成,它的範圍是「動態」:

如果指數爲:尾數將代表整個數字,那麼,以後,也不會由於尾數位數的限制,能夠代表例如尾數2。

如果指數是:尾數會代表越來越小的負冪2(1/2,1/4等),它會更精確。

問題本身: 如果未指定IEEE 754中定義的舍入模式之一,則缺省值爲「round-to-nearest-even」,這正是它聽起來的樣子。

當您使用最大雙倍值進行操作時,它與最後一個可表示雙倍值之間的差距很大。因此,減去1.0,代數給出了maxDouble - 1.0,但在硬件中,它不可表示,對於指數太小(它會反映在第52位後的變化中),所以您的FPU使用輪到最接近的舍入模式, 並輪到maxDouble。

要解決您的問題,您可以使用兩種解決方案。如果您的程序計算的值範圍不是太大,並且計算速度沒有太多要求,則使用定點算法。或者使用CPU製造商提供的內置函數(通常在頭文件中找到)將舍入模式設置爲舍入爲0或舍入。

哦,下面是一個舍入模式的簡短列表:舍入到最接近的偶數,向上舍入,向下舍入爲0,相當於舍入或舍入,取決於操作的符號。

而且,如果要使用浮點運算高的值進行編碼,則應定期檢查您的編號是否已飽和到∞或-∞,因爲那樣您將無法對它們應用操作。

+0

C++不要求**'double'是符合binary64的IEE 745,儘管這是迄今最常見的實現。 –

+0

編輯!雖然這個標準並不要求,但幾乎所有的CPU都有本地支持(除了一些嵌入式系統),所以很容易混淆。我很抱歉。 –

+0

相關問題:https://stackoverflow.com/questions/34294938/does-the-c-standard-specify-anything-on-the-representation-of-floating-point-n –

6

A double正在使用IEEE 754標準進行表示。不像int沒有爲1的固定最小步長不是作爲更大的數字變大作爲最小步長變: enter image description here

你的號碼的價值是如此之大,步長比1大得多。爲了簡單起見,我們假設它是10.所以如果你想減去1,那麼這個值會四捨五入到下一個有效的double。這和以前一樣。

或換句話說:17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873817718091929988125040402618412485836 是不是一個有效的雙。

+0

推測該圖非常誇張?如果我記得這裏的實際截止點在10^23左右。 – Puppy

+1

是的,這不準確。我試圖簡化問題。 – Crigges