2012-10-03 90 views
3

由於代碼段如下,我只是想知道C++ 32位VS 64的浮動限制

  • 爲什麼長雙的最大值是64位比32位更小?
  • 爲什麼64位版本不能像32位版本那樣擴展數量以填充「40」精度輸出?
  • 看來LDBL_MIN和LDBL_MAX的值是相等的,是一個錯誤嗎?

我已經查看了我的機器中的float.h文件,但找不到這些宏常量的顯式定義。

測試代碼(平臺= Win7-64bit)

#include <cfloat> 
#include <iomanip> 
cout<<"FLT_MAX ="<< setprecision(40) << FLT_MAX << endl; 
cout<<"DBL_MAX ="<< setprecision(40) << DBL_MAX << endl; 
cout<<"LDBL_MAX ="<< setprecision(40) << LDBL_MAX << endl; 
cout<<"FLT_MIN ="<< setprecision(40) << FLT_MIN << endl; 
cout<<"DBL_MIN ="<< setprecision(40) << DBL_MIN << endl; 
cout<<"LDBL_MIN ="<< setprecision(40) << LDBL_MIN << endl; 

32位結果(MinGW的-20120426)

FLT_MAX =340282346638528859811704183484516925440 
DBL_MAX =1.797693134862315708145274237317043567981e+308 
LDBL_MAX =1.189731495357231765021263853030970205169e+4932 
FLT_MIN =1.175494350822287507968736537222245677819e-038 
DBL_MIN =2.225073858507201383090232717332404064219e-308 
LDBL_MIN =3.362103143112093506262677817321752602598e-4932 

64位結果(MinGW64-TDM 4.6)

FLT_MAX =340282346638528860000000000000000000000 
DBL_MAX =1.7976931348623157e+308 
LDBL_MAX =1.132619801677474e-317 
FLT_MIN =1.1754943508222875e-038 
DBL_MIN =2.2250738585072014e-308 
LDBL_MIN =1.132619801677474e-317 

謝謝。

[編輯]:使用最新的MinGW64-TGM 4.7.1,LDBL_MAX,LDBL_MIN的「錯誤」似乎被刪除。

+0

雖然'.cpp'通常用於C++文件,CPP通常用於指代C預處理器。相應地修正了標題。 – 0xC0000022L

回答

3

LDBL_MAX =1.132619801677474e-317聽起來像是某處的錯誤。標準要求每個可表示爲double的值也可以表示爲long double,因此不允許LDBL_MAX < DBL_MAX。鑑於你沒有顯示你的真實測試代碼,我個人會在責備編譯器之前檢查它。

如果long double在兩者之間確實存在差異(非bug),則差異的基礎是32位編譯器使用舊的x87浮點運算,它具有80位精度,以及因此允許80位long double

您的64位編譯器在x64中使用較新的64位浮點操作。沒有80位精度,並且不會打擾切換到x87指令來實現更大的long double

這可能比這更復雜。例如,並非所有x86編譯器都必須具有80位long double。他們如何做出這個決定取決於各種事情,可能包括SSE2具有64位浮點運算的事實。但是可能性是long doubledouble的尺寸相同,或者它更大。

爲什麼64位版本不能像32位版本 那樣擴展數量以填充「40」精度輸出?

一個雙精度只有15位十進制數。除此之外的數字有時會提供信息,但通常會產生誤導。

我不記得標準中關於setprecision的內容是什麼,但假設允許執行畫一條停止產生數字的行,則double的精度是繪製它的合理位置。至於爲什麼一個實現決定實際執行而另一個沒有 - 我不知道。由於它們的分佈不同,它們可能會使用完全不同的標準庫。

相同的「雜散精度」就是爲什麼在一種情況下您看到340282346638528859811704183484516925440爲FLT_MAX,而在另一種情況下爲340282346638528860000000000000000000000。一個編譯器(或者說,一個庫實現)已經很難計算大量的數字。另一個已經放棄了,並且圓了。

0

爲了回答這個問題,我只做了一些假設: 1)你只在64位機器上測試過這個,2)編譯器是相同子版本的不同位版本(也就是說,他們實際上是姐妹編譯器)。

雖然這樣說:

從 「ISO/IEC 14882國際標準第一版1998-09-01」

3.9.1基本類型

  1. 有三種浮動點類型:float,double和long double。 double類型至少提供與float相同的精度,long double類型的精度至少與double相當。 float類型的值的集合是類型double的值集合的子集;類型double的值集合是long double類型的值集合的子集。浮點類型的值表示是實現定義的。積分類型和浮點類型統稱爲算術類型。標準模板numeric_limits(18.2)的專業化應指定實現的每種算術類型的最大值和最小值。

另外不同的CPU都會對最終的結果有不同的影響,只要有更高層次的數字精度。編譯器也一樣。 VC++的編譯器不會和borland,GCC/G ++等一樣。

+0

當然,我運行64位框中的測試程序,並且gcc(32/64)都是4.6.x,我知道這些限制在某種程度上是特定於實現的,但從結果來看,LDBL_MAX似乎很小數字,這比64位的DBL_MAX(317 + 308 = 625的數量級)要少得多 –

+0

我的理論是爲什麼這是因爲編譯器選擇如何表示它(通過宏或系統請求),或者是一個錯誤。 – M4rc