代码之家  ›  专栏  ›  技术社区  ›  Rafael

为什么这段代码返回两个不同的值进行相同的操作?

  •  4
  • Rafael  · 技术社区  · 8 年前
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main()
    {
        double a;
        double b;
        double q0 = 0.5 * M_PI + 0.5 * -2.1500000405000002;
        double q1 = 0.5 * M_PI + 0.5 * 0.0000000000000000;
        double w0 = 0.5 * M_PI + 0.5 * -43000.0008100000050000;
        double w1 = 0.5 * M_PI + 0.5 * -0.0000000000000000;
        double m = 1;
        double g = 43000000.81;
        double l1 = 0.1;
        double l2 = 0.1;
        double h = 0.0001;
    
        a = ((-g / l1) * sin(q0) + (sin(q1 - q0) * (cos(q1 - q0) * (w0 * w0 + (g / l1) * cos(q0)) + l2 * (w1 * w1 / l1))) / (m + pow(sin(q1 - q0), 2)));
        a = h * a;
    
        b = h * ((-g / l1) * sin(q0) + (sin(q1 - q0) * (cos(q1 - q0) * (w0 * w0 + (g / l1) * cos(q0)) + l2 * (w1 * w1 / l1))) / (m + pow(sin(q1 - q0), 2)));
    
        printf("%.20lf ", a);
        printf("%.20lf", b);
        return 0;
    }
    

    我的代码返回: -629.47620126173774000000 -629.47620126173763000000

    2 回复  |  直到 8 年前
        1
  •  2
  •   aschepler    8 年前

    C标准(99和11)规定:

    具有浮点操作数的运算值、经过常规算术转换的值和浮点常数的值的计算格式,其范围和精度可能大于类型所需的范围和精度。

    所以在一个表达式中,例如 h*(X+Y) 正如你在任务中所做的那样 b 的中间结果允许实现使用更高的精度 X+Y 可以存储在 double ,即使子表达式的类型仍然被认为是 . 但是在 a=X+Y; a=h*a; ,第一个赋值强制该值实际上可以存储在 双重的

    另一种可能性是编译器已经完成了“浮点压缩”。再次引用C标准,

    浮动表达式可以是 已签约 即,将其作为原子操作进行评估,从而忽略源代码和表达式评估方法所隐含的舍入误差。

    假设其中一个或两个是原因,您的价值 b 可能是您指定的计算的更精确表示(假设所有输入都限制为可以在 双重的 ).

    关于宏的cppreference页面 FLT_EVAL_METHOD 更详细地讨论了这两个问题。了解您的价值可能很有趣 FLT\u EVAL\u方法 然后玩 #pragma STDC FP_CONTRACT OFF .

        2
  •  0
  •   0___________    8 年前

    c d e不必等于x=b c y=d e和a.=x y

    这是因为浮点运算的精度有限。

    推荐文章