C++ c++;sqrt保证精度,上限/下限

C++ c++;sqrt保证精度,上限/下限,c++,c++11,floating-point,floating-accuracy,sqrt,C++,C++11,Floating Point,Floating Accuracy,Sqrt,我必须检查一个包含平方根的不等式。为了避免由于浮点不准确和舍入而导致的错误结果,我使用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);

我必须检查一个包含平方根的不等式。为了避免由于浮点不准确和舍入而导致的错误结果,我使用
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);
#包括//DBL\u MAX
#包括//std::nextafter,std::sqrt
双x=42.0//只是一个例子
双y=std::nextafter(std::sqrt(x),DBL_MAX);
a) 使用GCC编译器是否保证
y*y>=x

b) 这是否适用于其他操作,如
+-*/
或甚至
std::cos()
std::acos()

c) 有没有更好的方法来获取上限/下限

更新: 这不是由C++标准保证的,而是应该按照IEEE-75标准来工作的。这是否适用于GCC编译器?

对于GCC页面,如果您使用GCC内置sqrt函数
\uuuuuuBuiltin\uSQRT
,它将起作用

此外,这种行为将取决于您如何编译代码以及运行代码的机器

  • 如果处理器支持SSE2,则应使用标志
    -mfpmath=sse-msse2
    编译代码,以确保使用sse寄存器完成所有浮点操作

  • 如果处理器不支持SSE2,则应使用
    long double
    类型作为浮点值,并使用标记
    -ffloat store
    进行编译,以强制GCC不使用寄存器存储浮点值(这样做会导致性能损失)


  • 一般来说,浮点运算会导致一些错误。IEEE754要求大多数操作的结果在0.5ULP范围内是正确的,但误差可能会累积,这意味着结果可能不在精确结果的一个ULP范围内。精度也有限制,因此根据结果值中的位数,您也可能无法使用相同大小的值。超越函数在某种程度上也会在计算中引入误差

    然而,如果您使用的是GNU,sqrt将正确到0.5 ULP(四舍五入),因此您可以使用特定的示例(忽略
    NaN
    +/-0
    +/-Inf
    )。不过,最好定义一些epsilon作为您的错误容忍度,并将其用作界限。对于exmaple

    bool gt(double a, double b, double eps) {
    
      return (a > b - eps);
    }
    
    根据计算中需要的精度级别,您可能还希望使用长双精度

    所以,为了回答你的问题

    a) 是否使用GCC编译器保证y*y>=x

    假设您使用GNU glibc或SSE2内部函数,是的

    b) 这是否适用于其他操作,如+-*/甚至std::cos()和std::acos()

    假设您使用GNU glibc和一个操作,是的。虽然有些超验不能保证正确的四舍五入

    c) 有没有更好的方法来获取上限/下限

    您需要知道计算中的误差容限是多少,并将其用作ε(可能大于一个ULP)。

    c) 有没有更好的方法来获取上限/下限


    另一种方法是使用不同的,即
    FE\u向上
    FE\u向下
    ,而不是默认的
    FE\u最短
    。请看,这可能是,但是一个更好的上限/下限。

    您是要求此特定情况,还是一般要求任何浮点数?NaN马上就打破了任何逻辑。据我所知,标准没有对实现作出任何保证
    std::sqrt
    ,因此我认为这个问题的答案将取决于实现。@MarkB我是指任何(正)浮点数,42只是一个例子。您可能对此感兴趣(查找
    sqrt
    )。