简体   繁体   English

在 Windows10 与 Debian GNU/Linux 10 中生成不同输出的数值过程

[英]Numerical Procedure generating different outputs in Windows10 vs Debian GNU/Linux 10

I was playing arround with the Maehly Procedure to polish the roots of a polinomial and stumbled upon something interessing: The exact samame code gave me two really different outputs depending on the machine it was compiled on.我正在使用 Maehly 程序来完善多项式的根,并偶然发现了一些有趣的东西:根据编译它的机器,确切的相同代码给了我两个非常不同的输出。

The Code编码

#include <stdio.h>

#define MAX_ITERATION 1000

double poly(double x){
    double coeff[9]={-61.688, 72.5235, 72.822, -108.519, -5.12949, 39.9139,-7.07373, -3.91823, 1.0};
    double result=coeff[0];
    double buffer;
    
    for(int i=1; i<9;i++){
        buffer=coeff[i];
        for(int j=1;j<=i;j++){
            buffer*=x;
        }
        result+=buffer;
    }
    return result;

}
double poly_der(double x){
    double coeff[8]={ 72.5235, 72.822, -108.519, -5.12949, 39.9139,-7.07373, -3.91823, 1.0};
    double result=coeff[0];
    double buffer;
    
    for(int i=1; i<8;i++){
        buffer=coeff[i]*(i+1);
        for(int j=1;j<=i;j++){
            buffer*=x;
        }
        result+=buffer;
    }
    return result;
}

int main(){
    double roots[8]={0.9, -1.1, 1.4, 1.4, -2.0, -2.0, 2.2, 2.2};
    double factor;
    double pol_eval;
    //Implement Maehly-procedure

    for(int i=0; i<MAX_ITERATION;i++){ 
        for(int k=0;k<8;k++){
            factor=0;
            for(int j=0;j<k;j++){
                factor+=1/(roots[k]-roots[j]);
            }
            pol_eval=poly(roots[k]);
            roots[k]-=pol_eval/(poly_der(roots[k])-(pol_eval*factor));

        }
    }
   

    for(int i=0;i<8;i++){
        printf("\n%d: x:%0.16f poly:%e \n",i,roots[i],poly(roots[i]));
    }
}

The Windows output (Windows10): Windows output(Windows10):

0: x:1.0072928773885637 poly:-8.437695e-015 

1: x:-1.0004044550991309 poly:-2.375877e-014 

2: x:1.3770602924650244 poly:-3.552714e-015  

3: x:-2.5000428878301499 poly:0.000000e+000  

4: x:-1.7318124315476966 poly:-1.136868e-013

5: x:3.0001628929552053 poly:9.094947e-013

6: x:2.2341265341600458 poly:-2.273737e-013

7: x:3.0001628929552049 poly:0.000000e+000

The Linux Output(Debian GNU/Linux 10): Linux 输出(Debian GNU/Linux 10):

0: x:1.0072928773885637 poly:-8.437695e-15

1: x:-1.0004044550991309 poly:-2.375877e-14

2: x:1.3770602924650244 poly:-3.552714e-15

3: x:-2.5000428878301499 poly:0.000000e+00

4: x:-1.7318124315476959 poly:2.842171e-14

5: x:3.0001628929552093 poly:-1.818989e-12

6: x:2.2341265341600458 poly:-2.273737e-13

7: x:1.5318471775081237 poly:0.000000e+00

The x are the polished roots of the polinomial, start values are saved in the array roots[8] . x 是多项式的抛光根,起始值保存在数组 root roots[8]中。

Can you help me explain this behavior and,most important, help me understand how to avoid something similar in the future?你能帮我解释一下这种行为吗,最重要的是,帮助我了解如何避免将来发生类似的事情?

We have to 2 issue, why different?我们要2个问题,为什么不同? Which is better - or may a 3rd way?哪个更好 - 或者可能是第三种方式?

OP reports different FLT_EVAL_METHOD values of 2 and 0. This implies the Windows version is using long double math for intermediate calculations and the Linux one is just using double . OP 报告2 和 0 的不同FLT_EVAL_METHOD值。这意味着 Windows 版本使用long double数学进行中间计算,而 Linux 版本仅使用double Usually the FLT_EVAL_METHOD==2 is more correct.通常FLT_EVAL_METHOD==2更正确。

#include <float.h>
printf("%d\n", FLT_EVAL_METHOD);

FP have a weakness in subtracting values nearly the same. FP 在减去几乎相同的值方面有一个弱点。 The cancelation of many common bits leads to the slight computational errors becoming more significant.许多公共位的取消导致轻微的计算错误变得更加显着。 Different compilations may have slightly different rounded result for various reasons, although I'd _expect the same.由于各种原因,不同的编译结果可能略有不同,尽管我_expect 相同。 poly() does that with repeated calculations to find a power of x and then adding terms that cancel out. poly()通过重复计算来找到x的幂,然后添加抵消的项。

Alternative code below does far fewer calculations are certainly provide a better result for both systems.下面的替代代码所做的计算要少得多,肯定会为两个系统提供更好的结果。

double poly(double x) {
  const double coeff[9] = {-61.688, //
      72.5235, 72.822, -108.519, -5.12949, //
      39.9139, -7.07373, -3.91823, 1.0};
  double result = 0.0;
  for (int i = 9; i-- > 0; ) {
    result = result * x + coeff[i];
  }
  return result;
}

On my system FLT_EVAL_METHOD is 0.在我的系统FLT_EVAL_METHOD是 0。
Result of just changing poly() .只是改变poly()的结果。 Similar issue applies to poly_der() .类似的问题适用于poly_der()

0: x:1.0072928773885645 poly:0.000000e+00 
1: x:-1.0004044550991309 poly:-7.105427e-15 
2: x:1.3770602924650401 poly:-2.842171e-14 
3: x:3.0001628929552013 poly:3.552714e-13 
4: x:-1.7318124315476964 poly:-2.842171e-14 
5: x:-2.5000428878301499 poly:6.821210e-13 
6: x:2.2341265341600485 poly:-7.105427e-15 
7: x:1.5318471775081424 poly:3.552714e-14 

Fixing both poly() and poly_dev()修复poly()poly_dev()

static const double coeff[9] = {-61.688, //
    72.5235, 72.822, -108.519, -5.12949, //
    39.9139, -7.07373, -3.91823, 1.0};

double poly(double x) {
  double result = 0.0;
  for (int i = 9; i-- > 0; ) {
    result = result * x + coeff[i];
  }
  return result;
}

double poly_der(double x) {
  double result = 0.0;
  for (int i = 9; i-- > 1; ) {
    result = result * x + coeff[i]*i;
  }
  return result;
}

Results with only double math rival the weaker computational code using long double math.只有double数学的结果可以与使用long double数学的较弱计算代码相媲美。

printf("%d: x:% 0.16f poly:% e \n", i, roots[i], poly(roots[i]));
0: x: 1.0072928773885645 poly: 0.000000e+00 
1: x:-1.0004044550991309 poly:-7.105427e-15 
2: x: 1.3770602924650324 poly:-4.973799e-14 
3: x:-2.5000428878301495 poly:-6.394885e-13 
4: x:-1.7318124315476964 poly:-2.842171e-14 
5: x: 1.5318471775081377 poly: 0.000000e+00 
6: x: 2.2341265341600520 poly: 0.000000e+00 
7: x: 3.0001628929552009 poly:-2.771117e-13 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Windows10平台上_execl() function的使用 - usage of _execl() function on Windows10 platform windows10如何安装hlsdl - How to install hlsdl in windows10 Arduino IDE 找不到我的库目录 - Windows10 - Arduino IDE not finding my library directory - Windows10 在Windows和GNU / Linux上c mktime是不同的? - is c mktime different on Windows and GNU/Linux? gcc在windows上生成垃圾? windows vs linux - gcc on windows generating garbage? windows vs linux 在 Windows 10 上使用 VS2019 的 Linux (Raspbian) 中的 C/C++ 线程 -pthread - 无法编译 - C/C++ Threading in Linux (Raspbian) using VS2019 on Windows 10 -pthread - Can't compile 二叉树代码适用于 Linux 但不适用于 Windows 10 - Binary tree code works on Linux but not on Windows 10 lld-link错误:在Windows10上尝试与libcmt.lib链接时没有输入文件 - lld-link error: no input files when trying to link with libcmt.lib on Windows10 Eclipse 在 Windows10 中:在 C 中写入“hello world”,得到错误:最终启动序列中的错误 - Eclipse in Windows10 : write “hello world” in C, got error : error in final lauch sequence C - 在 Makefile MinGW32 - Windows10 中静态链接 GLFW - C - Staticaly link GLFW in Makefile MinGW32 - Windows10
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM