簡體   English   中英

如何在c ++中編寫可移植的浮點運算?

[英]How to write portable floating point arithmetic in c++?

假設您正在編寫一個執行大量浮點運算的C ++應用程序。 假設這個應用程序需要在合理范圍的硬件和操作系統平台上可移植(例如32位和64位硬件,Windows和Linux都是32位和64位版本......)。

您如何確保所有平台上的浮點算法都相同? 例如,如何確保所有平台上的32位浮點值真的是32位?

對於整數,我們有stdint.h但似乎沒有浮點等價物。


[編輯]

我得到了非常有趣的答案,但我想為這個問題增加一些精確度。

對於整數,我可以寫:

#include <stdint>
[...]
int32_t myInt;

並確保無論我在哪個(C99兼容)平台上,myInt都是32位整數。

如果我寫:

double myDouble;
float myFloat;

我確定這會在所有平台上分別編譯為64位和32位浮點數嗎?

非IEEE 754

一般來說,你不能。 在一致性和性能之間總是需要權衡,而C ++會為您提供幫助。

對於沒有浮點運算的平台(如嵌入式和信號處理處理器),您不能使用C ++“本機”浮點運算,至少不能這樣。 雖然軟件層是可能的,但對於這種類型的設備來說肯定是不可行的。

對於這些,您可以使用16位或32位定點算法(但您甚至可能會發現只支持基本的長 - 而且通常,div非常昂貴)。 然而,這將比內置的定點算術慢得多,並且在基本的四個操作之后變得很痛苦。

我沒有遇到過支持不同於IEEE 754格式的浮點的設備。 根據我的經驗,您最好的選擇是希望達到標准,否則您通常最終會圍繞設備的功能構建算法和代碼。 sin(x)突然花費1000倍時,你最好選擇一個不需要它的算法。

IEEE 754 - 一致性

我在這里發現的唯一不可移植性是當你期望跨平台的比特結果相同時。 最大的影響是優化者。 同樣,您可以交換准確性和速度以保持一致性。 大多數編譯器都有一個選項 - 例如Visual C ++中的“浮點一致性”。 但請注意,這總是超出標准保證的准確性。

為什么結果不一致? 首先,FPU寄存器通常具有比double(例如80位)更高的分辨率,因此只要代碼生成器不將值存儲回來,就可以以更高的精度保持中間值。

其次,由於精度有限, a*(b+c) = a*b + a*c等等不精確。 盡管如此,優化器(如果允許)可以使用它們。

此外 - 我學到了很多困難 - 打印和解析功能在各個平台上不一定一致,可能也是由於數字不准確。

浮動

一種常見的誤解是,浮動操作本質上比雙重更快。 通過單獨減少緩存未命中,處理大型浮點數組的速度更快。

浮動精度要小心。 它可以在很長一段時間內“足夠好”,但我經常看到它失敗的速度比預期的要快。 由於支持SIMD,基於浮點數的FFT可以更快,但是在音頻處理的早期階段就會產生顯着的假象。

使用固定點。

但是,如果您希望接近可能進行可移植浮點運算的領域,則至少需要使用controlfp來確保一致的FPU行為,並確保編譯器對浮點運算強制執行A​​NSI一致性。 為何選擇ANSI? 因為它是標准。

即便如此,您也無法保證可以生成相同的浮點行為; 這也取決於您運行的CPU / FPU。

這應該不是問題, IEEE 754已經定義了浮點布局的所有細節。

可存儲的最大值和最小值應在limits.h中定義

便攜式是一回事,在不同平台上產生一致的結果是另一回事。 根據您的嘗試,編寫可移植代碼應該不會太困難,但在任何平台上獲得一致的結果幾乎是不可能的。

我相信“limits.h”將包括C庫常量INT_MAX及其兄弟。 但是,最好使用“限制”及其定義的類:

std::numeric_limits<float>, std::numeric_limits<double>, std::numberic_limits<int>, etc...

如果您假設您將在另一個系統上獲得相同的結果,請閱讀什么可能導致確定性過程首先生成浮點錯誤 您可能會驚訝地發現,在同一台機器上的不同運行中,您的浮點運算甚至不同!

暫無
暫無

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

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