【问题标题】:Same numerical code returns different output whether it is in C++ or C无论是 C++ 还是 C,相同的数字代码都会返回不同的输出
【发布时间】:2017-01-07 15:59:12
【问题描述】:

我得到了一个示例 C++ 数字代码,以三种不同的方式计算导数。我必须将它转换为 C。我认为它不会因为原来使用 cmath 而给我带来任何问题,但我错了。这是原始代码:

#include <iostream>
#include<string>
#include <cmath>
#include <fstream>
using namespace std;


double metoda_pochodna_1(int x, double h)
{
    return (sin(x+h) - sin(x)) / h;
}   
double metoda_pochodna_2(int x, double h)
{
    return (sin(x+(0.5*h)) - sin(x-(0.5*h))) / h;
}
double metoda_pochodna_3(int x, double h)
{
    return ((sin(x-2*h) - 8*sin(x-h) + 8*sin(x+h) - sin(x+2*h)) / (12*h));
}


int main()
{
    double h, w1, w2, w3, kos = cos(1.0);
    int x=1;
    ofstream wyniki;
    wyniki.open("wyniki.dat");

    for (h = pow(10.0, -15.0); h < 1; h *= 1.01) 
    {
        w1 = log10(abs(metoda_pochodna_1(x,h) - kos));
        w2 = log10(abs(metoda_pochodna_2(x,h) - kos));
        w3 = log10(abs(metoda_pochodna_3(x,h) - kos));
        wyniki << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
        cout << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
    }

    wyniki.close();
    cout << endl;
    /*system("pause");*/ //uruchamiane z windowsa
    return 0;
}

这是我的 C 版本;我刚刚更改了文件处理。注意:我在故障排除期间更改为long double,但结果输出与使用常规double 的版本完全相同。

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



long double metoda_pochodna_1(int x,long  double h)
{
    return (sin(x+h) - sin(x)) / h;
}   
long double metoda_pochodna_2(int x,long  double h)
{
    return (sin(x+(0.5*h)) - sin(x-(0.5*h))) / h;
}
long double metoda_pochodna_3(int x, long double h)
{
    return ((sin(x-2*h) - 8*sin(x-h) + 8*sin(x+h) - sin(x+2*h)) / (12*h));
}


int main()
{
    long double h, w1, w2, w3, kos = cos(1.0);
    int x=1;
    FILE * file;
    file = fopen("wyniki.dat","w+");


    for (h = pow(10.0, -15.0); h < 1; h *= 1.01) 
    {
        w1 = log10(abs(metoda_pochodna_1(x,h) - kos));
        w2 = log10(abs(metoda_pochodna_2(x,h) - kos));
        w3 = log10(abs(metoda_pochodna_3(x,h) - kos));
        fprintf(file,"%f %Lf %Lf %Lf\n",log10(h), w1,w2,w3);
        printf("%f %Lf %Lf %Lf\n",log10(h), w1,w2,w3);
        //wyniki << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
        //cout << log10(h)<<"  "<< w1 <<"  "<< w2 <<"  "<< w3 << "\n";
    }

    fclose(file);
    printf("\n");
    return 0;
}

这是 C++ 代码的输出,我假设它是正确的:

-15  -1.82947  -1.82947  -1.28553

-14.9957  -2.03091  -2.03091  -1.33768

14.9914  -2.41214  -2.41214  -1.39632

-14.987  -2.81915  -2.81915  -1.46341

[...]

而这是C版的输出,明显不同(前行的附加精度是来自long double,但是其他三列都是-inf不管是double还是long double ):

-15.000000 -inf -inf -inf

-14.995679 -inf -inf -inf

-14.991357 -inf -inf -inf

-14.987036 -inf -inf -inf

[...]

我的转换代码有什么问题?

【问题讨论】:

  • 我注意到打印为-inf 的值是%Lf 格式说明符的输出。您是否尝试过已知值(未计算)的简单测试输出?
  • 那么为什么你认为不同语言C和C++应该表现相同呢?看看minimal reproducible example 是什么意思!
  • 在 C 中 abs 是一个 integer 函数。使用fabs
  • 已解决:使用 fabs() 而不是 abs() 可以一切正常。谢谢!我在使用 %Lf 说明符的地方提供了测试已知值,它们正确显示。这不是输出数据的问题。当使用 printf 和 fprintf 输出 long double 时,%Lf 对于 POSIX 系统是正确的。我知道 C 和 C++ 是不同的语言,但是在使用相同的 cmath 库进行如此简单的计算时,至少得到不同的结果会很奇怪......
  • abs() 不是 C 数学库的一部分(尽管 fabs() 是)。 abs()stdlib.h 中声明。

标签: c++ c numerical derivative calculus


【解决方案1】:

您正在使用abs,它是一个整数函数。 C 浮点函数是fabs。 将您的三行更改为

w1 = log10(fabs(metoda_pochodna_1(x,h) - kos));
w2 = log10(fabs(metoda_pochodna_2(x,h) - kos));
w3 = log10(fabs(metoda_pochodna_3(x,h) - kos));

程序输出更合理的值。

【讨论】:

  • 解决了!现在的值正在检查中。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-29
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多