[英]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
,它將起作用。
此外,此行為將取決於您編譯代碼的方式以及運行它的計算機
如果處理器支持SSE2,那么您應該使用標志-mfpmath=sse -msse2
編譯代碼,以確保使用SSE寄存器完成所有浮點操作。
如果處理器不支持SSE2,則應使用long double
類型作為浮點值,並使用標志-ffloat-store
進行編譯,以強制GCC不使用寄存器來存儲浮點值(您將受到性能損失)這樣做)
關於
c)是否有更好的方法來獲得上限/下限?
另一種方法是使用不同的舍入模式 ,即FE_UPWARD
或FE_DOWNWARD
而不是默認的FE_TONEAREST
。 請參閱https://stackoverflow.com/a/6867722這可能會更慢 ,但上限/下限更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.