罪过,cos,棕褐色不准确

Sco*_*ttD 5 floating-point trigonometry floating-accuracy

sinl当参数接近pi的非零倍数时,为什么给出不正确的结果?sinl当参数很大时,为什么会给出错误的结果?以下代码说明了这一点。

注意,用于初始化变量pi的数字与任何64位long double值都不完全匹配。编译器选择最接近的值3.14159265358979323851280895940618620443274267017841339111328125。可以使用libquadmath,gnu MPFR lib或在线计算器(例如http://www.ttmath.org/online_calculator)找到期望的正弦值。

#include <stdio.h>
#include <math.h>

int main (int argc, char *argv [])
    {
    volatile long double pi = 3.14159265358979323846L;
    volatile long double big = 9223372035086174241L;
    volatile long double expected1 = -5.0165576126683320235E-20L;
    volatile long double expected2 = -4.2053336735954077951E-10L;
    double result;
    double ex1 = expected1, ex2 = expected2;

    result = sinl (pi);
    printf("expected: %g, \nreturned: %g\n\n", ex1, result);
    result = sinl (big);
    printf("expected: %g, \nreturned: %g\n\n", ex2, result);
    return 0;
    }
Run Code Online (Sandbox Code Playgroud)

我正在使用gcc 4.7.3。使用volatile可以防止编译器将sinl()调用替换为硬编码结果。我的计算机装有Intel Core i7处理器并运行Windows。我将结果打印为double而不是long double,因为我使用的gcc的mingw端口不支持打印long double。这是程序输出:

expected: -5.01656e-020,
returned: -5.42101e-020

expected: -4.20533e-010,
returned: -0.011874
Run Code Online (Sandbox Code Playgroud)

小智 3

该错误可以追溯到 sinl 库代码使用的 fsin 处理器指令。正如英特尔声称的那样,fsin、fcos 和 fptan 指令不精确到 1.0 ulp: http: //notabs.org/fpuaccuracy/