簡體   English   中英

在C ++中處理難以置信的精確浮點計算時,保持准確性的標准方法是什么?

[英]What is the standard way to maintain accuracy when dealing with incredibly precise floating point calculations in C++?

我正在從Scilab (類似於Matlab)將程序轉換為C ++的過程中,並且需要保持與先前代碼相同的精度。

注意:盡管保持相同的精度水平是理想的。 如果最終結果有一些錯誤,這是可以接受的。 我面臨的問題(如下所述)是由於循環造成的,因此計算錯誤很快就形成了。 但是,如果最終結果只有千分之一左右(例如1/1000與1/1001),那將不是問題。

我簡要地研究了許多不同的方法來做到這一點,包括:

Int vs Float示例: 不用浮點數12.45,而是將其存儲為124,500的整數。 然后在適當的時候簡單地將所有內容轉換回去。 注意:我不太確定這將如何與我正在使用的代碼一起工作(下面有更多詳細信息)。

我的程序如何產生錯誤結果的示例:

for (int i = 0; i <= 1000; i++)
{
    for (int j = 0; j <= 10000; j++)
    {
        // This calculation will be computed with less precision than in Scilab
        float1 = (1.0 / 100000.0);

        // The above error of float2 will become significant by the end of the loop
        float2 = (float1 + float2);
    }
}

我的問題是:

是否有一種公認的方法來保持浮點算術中的精度,還是上述方法之一足夠?

移植這樣的代碼時,保持精度非常困難。 不是因為語言對float有隱含的不同float ,而是因為有不同的算法或精度限制假設。 例如,在Scilab中執行數值積分時,它可以使用高斯求積法。 而您可以嘗試使用梯形方法。 兩者可能都在相同的IEEE754單精度浮點數上工作,但是由於兩種算法的收斂特性,您將獲得不同的答案。 那么如何解決這個問題?

好了,您可以瀏覽Scilab源代碼,並查看它用於您所需的所有算法的所有算法。 然后,您可以復制這些算法,以照顧Scilab隱式執行的數據的任何預處理或后處理(如果有的話)。 這是很多工作。 而且,坦率地說,這可能不是花費時間的最佳方式。 相反,我將研究使用開發人員文檔中的“ 與其他語言交互”部分,以了解如何直接從C,C ++,Java或Fortran代碼調用Scilab函數。

當然,使用第二種方法時,您必須考慮如何分發代碼(如果需要)。Scilab具有GPL兼容許可證,因此您可以將其與代碼捆綁在一起。 但是,它很大(〜180MB),您可能只想打包所需的部分(例如,不需要整個解釋器系統)。 這是另外一種工作方式,但是可以保證與當前Scilab解決方案的數值兼容性。

是否有一種公認的方法來保持浮點運算的精度

“普遍接受”的范圍太廣,所以沒有。

以上方法之一足夠嗎?

是。 特別是gmp似乎是標准選擇。 我還將看一下Boost Multiprecision庫

手工編碼的整數方法也可以使用,但肯定不是選擇的方法:它需要更多的編碼,並且更嚴格的方法是存儲和處理精確的整數。

如果您的編譯器支持,請使用BCD(二進制編碼的十進制)

山姆

好吧,如果您使用GCC編譯器,另一種選擇是使用quadmath / __ float128類型。

暫無
暫無

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

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