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) y*y >= x
保证使用GCC编译器吗?
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
)。虽然,最好是定义一个作为容错范围然后用它作为界。例如,
bool gt(double a, double b, double eps) {
return (a > b - eps);
}
根据您需要的计算精度级别,您也可能希望使用long double
来代替。
那么,为了回答你的问题…
a) y*y>= x保证使用GCC编译器?
假设您使用GNU glibc或SSE2 intrinsic,可以。
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这可能较慢,但是一个更好的上/下界。
- 为什么组合的上限和下限比较的计算结果总是为 true?
- 上限/下限没有像我预期的那样工作,无法理解为什么
- 虚拟函数调用的性能作为 for 循环中的上限
- 为什么下限不适用于向量对
- 以 CPP 为单位设置的下限
- 在 c++ 中的 multiset<pair<int,int> > 中查找下限
- SDL 帧速率上限实施
- 下限误差
- 使用对象指针向量的下限
- 如何递归枚举每个元素都有上限的所有可能的数组
- C++在局部变量的内存上是否有上限
- C++高效的整数下限功能
- 下限上限给出相同的结果
- 如果我们有对的矢量,如何进行下限二进制搜索
- 了解下限/上限接口
- 如何在C++中设置短整型的上限和下限字节
- C++舍入数字,不带上限或下限
- 带有上限和下限的C++Cout数组值
- 浮点数的上限和下限是如何确定的
- c++ SQRT保证精度,上限/下限