簡體   English   中英

為什么編譯時浮點計算可能與運行時計算的結果不同?

[英]Why compile-time floating point calculations might not have the same results as run-time calculations?

constexpr:Introduction中 ,發言者提到“編譯時浮點計算可能與運行時計算的結果不同”: 在此輸入圖像描述

原因與“交叉編譯”有關。

老實說,我無法清楚地理解這個想法。 恕我直言,不同的平台也可能有不同的整數實現。

為什么它只影響浮點數? 或者我想念什么?

你是絕對正確的,在某種程度上,在編譯時計算浮點值的問題與計算整數值的問題是一樣的。 不同之處在於任務的復雜性。 在具有16位寄存器的系統上模擬24位整數數學是相當容易的。 對於認真的程序員來說,這是一個手指練習。 如果你沒有本機實現,那么做浮點數學要困難得多。 不要求浮點constexpr的決定部分基於這種差異:要求交叉編譯器在編譯時為其目標平台模擬浮點數學將是非常昂貴的。

另一個因素是可以在運行時設置浮點計算的一些細節。 舍入是一個; 處理溢出和下溢是另一回事。 編譯器根本無法知道浮點計算的運行時評估的完整上下文,因此無法可靠地在編譯時計算結果。

為什么它只影響浮點數?

對於標准,不對浮點運算精度施加限制。

根據expr.const強調我的

[注意:由於本文檔對浮點運算的准確性沒有任何限制 ,因此未指定在轉換期間對浮點表達式的求值是否與對同一表達式的求值產生相同的結果(或者對程序執行期間的相同值)。 [例如:

 bool f() { char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // May be evaluated at runtime return sizeof(array) == size; } 

未指定f()的值是true還是false - 結束例子]
- 結束說明]

為什么它只影響浮點數?

對整數的一些操作無效且未定義:

  • 除以零:沒有為操作數定義的數學運算
  • 溢出:給定類型無法表示的數學值

[編譯器將在編譯時值上檢測此類情況。 在運行時,行為不是由標准定義的,可以是任何東西,例如,如果編譯器假定操作有效,則拋出信號,模運算或“隨機”行為。

對數組有效的整數的操作是完全以數學方式指定的

C / C ++(和大多數編程語言)中的整數除法是一個精確的操作,因為它是歐幾里德除法,而不是試圖找到有理數除法的近似逼近: 5/35/3 3的無限十進制表示是1.66 ...或約1.66666667; 最接近的整數是2。

fp的目的是提供關於“實數”的數學運算的最佳近似值(對於四個運算實際上是有理數,浮點數是合理的定義)。 根據使用std::fesetround設置的std::fesetround 舍入模式對這些操作進行舍 因此fp操作是依賴於狀態的,結果不僅僅是操作數的函數。 (參見std :: fegetround,std :: fesetround 。)

在編譯時沒有這樣的“狀態”,因此根據定義,編譯時fp操作不能與運行時操作一致。

暫無
暫無

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

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