簡體   English   中英

c ++ sqrt保證精度,上限/下限

[英]c++ sqrt guaranteed precision, upper/lower bound

我必須檢查包含平方根的不等式。 為了避免由於浮點不准確和舍入導致的錯誤結果,我使用std::nextafter()來獲取上限/下限:

#include <cfloat> // DBL_MAX
#include <cmath> // std::nextafter, std::sqrt

double x = 42.0; //just an example number
double y = std::nextafter(std::sqrt(x), DBL_MAX);

a)使用GCC編譯器是否保證y*y >= x

b)這適用於其他操作,如+ - * /甚至std::cos()std::acos()嗎?

c)是否有更好的方法來獲得上限/下限?

更新:我讀過這不是C ++標准保證的,但應該按照IEEE-754工作。 這適用於GCC編譯器嗎?

通常,浮點運算將導致一些ULP錯誤。 IEEE 754要求大多數操作的結果在0.5 ULP內正確,但錯誤可能累積,這意味着結果可能不在精確結果的一個ULP內。 精度也有限制,因此根據結果值中的位數,您也可能無法使用相同大小的值。 先驗函數在將錯誤引入計算方面也有些臭名昭着

但是,如果您使用的是GNU glibc ,則sqrt將在0.5 ULP(舍入)范圍內正確,因此您的具體示例將起作用(忽略NaN+/-0+/-Inf )。 雖然,最好將一些epsilon定義為您的容錯,並將其用作綁定。 例如,

bool gt(double a, double b, double eps) {

  return (a > b - eps);
}

根據計算中所需的精度級別,您可能還需要使用long double

那么,回答你的問題......

a)使用GCC編譯器是否保證y * y> = x?

假設您使用GNU glibc或SSE2內在函數,是的。

b)這適用於其他操作,如+ - * /甚至std :: cos()和std :: acos()嗎?

假設你使用GNU glibc和一個操作,是的。 雖然一些超驗主義並未得到正確的保證。

c)是否有更好的方法來獲得上限/下限?

您需要知道計算中的誤差容限,並將其用作epsilon(可能大於一個ULP)。

對於GCC, 頁面表明如果您使用GCC內置sqrt函數__builtin_sqrt ,它將起作用。

此外,此行為將取決於您編譯代碼的方式以及運行它的計算機

  1. 如果處理器支持SSE2,那么您應該使用標志-mfpmath=sse -msse2編譯代碼,以確保使用SSE寄存器完成所有浮點操作。

  2. 如果處理器不支持SSE2,則應使用long double類型作為浮點值,並使用標志-ffloat-store進行編譯,以強制GCC不使用寄存器來存儲浮點值(您將受到性能損失)這樣做)

關於

c)是否有更好的方法來獲得上限/下限?

另一種方法是使用不同的舍入模式 ,即FE_UPWARDFE_DOWNWARD而不是默認的FE_TONEAREST 請參閱https://stackoverflow.com/a/6867722這可能會更慢 ,但上限/下限更好。

暫無
暫無

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

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