2012-08-30 45 views
17

我目前正在進行數值計算的C++項目。絕大多數的代碼都使用單精度浮點值,並且完全適用於此。正因爲如此,我使用編譯器標誌來設置基本浮點文字單精度而不是雙精度,這是默認值。我發現這使得表達式更易於閱讀,我不必擔心在某處忘記了'f'。然而,我偶爾需要雙精度計算提供的額外精度,而我的問題是如何將雙精度文字轉換爲這種表達式。我迄今試過的每種方法都是先將值存儲在單個精度變量中,然後將截斷值轉換爲雙精度值。不是我想要的。在C++中是否有一個浮點數字後綴來進行數字雙精度?

我已經嘗試過的一些方法到目前爲止在下面給出。

#include <iostream> 

int main() 
{ 
    std::cout << sizeof(1.0E200) << std::endl; 
    std::cout << 1.0E200 << std::endl; 

    std::cout << sizeof(1.0E200L) << std::endl; 
    std::cout << 1.0E200L << std::endl; 

    std::cout << sizeof(double(1.0E200)) << std::endl; 
    std::cout << double(1.0E200) << std::endl; 

    std::cout << sizeof(static_cast<double>(1.0E200)) << std::endl; 
    std::cout << static_cast<double>(1.0E200) << std::endl; 

    return 0; 
} 

使用單精度常數運行會得出以下結果。

~/path$ g++ test.cpp -fsingle-precision-constant && ./a.out 
test.cpp:6:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] 
test.cpp:7:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] 
test.cpp:12:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] 
test.cpp:13:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] 
test.cpp:15:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] 
test.cpp:16:3: warning: floating constant exceeds range of ‘float’ [-Woverflow] 
4 
inf 
16 
1e+200 
8 
inf 
8 
inf 

這是我的理解是,後兩種情況下提供的8個字節應該足以容納1.0E200,通過下面的輸出,其中相同的程序,而不-fsingle精恆編譯支持的理論。

~/path$ g++ test.cpp && ./a.out 
8 
1e+200 
16 
1e+200 
8 
1e+200 
8 
1e+200 

可能的解決方法由上述實施例建議的是使用四倍精度浮點文字到處我原本需要時通過庫和這種使用雙精度,並澆鑄成雙精度。但是,這感覺有點浪費。

我還能做什麼?

+0

未經審訊,但'的strtod (「1e + 200」)可能會被優化爲您希望的雙精度浮點常量。 –

+4

我不知道,這聽起來有點像你正在爲自己創造一個問題。爲什麼不把它保留原樣並將'f'附加到不需要雙精度的所有內容? – Mysticial

+1

你可以把你的雙常量放在一個單獨的文件中,並且不用'-fsingle-precision-constant'標誌來編譯它。 –

回答

19

就像馬克說的那樣,標準說它的雙倍除非它的後面跟着一個f。

標準背後有很好的理由,爲了方便使用編譯器標誌來繞過它是不好的做法。

所以,正確的做法是:

  1. 刪除編譯器標誌
  2. 浮點變量存儲雙值時,修正有關的精度損失所有的警告(在所有的F後綴添加)
  3. 當你需要加倍時,省略f後綴。

它可能不是你正在尋找的答案,但它是你應該使用的方法,如果你關心你的代碼庫的長久性。

+0

究竟是什麼「好理由」?它看起來更像是一個限制,使得特殊的國旗很難使用。另外,使用'double(1.0E200L)'有什麼問題?這如何影響長壽? –

+0

代碼庫不應限於特定的編譯器。編譯器應符合標準。一個標準應該是真理的一個來源。它會影響壽命,因爲不符合標準會隨着時間的推移而引入不一致性,因爲各種程序員在代碼庫上工作,並且每個人都以他們喜歡的方式進行操作。這是標準存在的原因。 – Carl

11

如果你讀2.13.3/1,你會看到:

類型浮動文字的兩倍,除非後綴明確指定 。後綴f和f指定float,後綴l和L 指定long double。

換句話說,沒有後綴指定double的字面浮點常量如果更改默認float。不幸的是,在這種情況下,你不可能擁有兩全其美。

+1

-1,'double(1.0E200L)'工作正常。 – orlp

+0

沒關係,提問者在問題中提出了這個問題,並發現它「浪費」。 – orlp

5

你不能定義自己的後綴,但也許宏象

#define D(x) (double(x##L)) 

會爲你工作。編譯器應該只是發出一個雙常量,並且在我的系統上出現-O2

+0

+1僅僅用於檢查編譯器是否發出一個雙常數,當我對這個問題發表評論時,我懶得去做:-) –

8

如果你能負擔得起GCC 4.7或鐺3.1,使用用戶定義的文字:

double operator "" _d(long double v) { return v; } 

用法:

std::cout << sizeof(1.0E200_d) << std::endl; 
std::cout << 1.0E200_d << std::endl; 

結果:

8 
1e+200 
相關問題