c程序中的隐藏错误(数值计算)

时间:2014-02-11 19:38:34

标签: c gcc numerical-methods

这是2个功能。我发现它们之间没有重要区别,但结果却不同。为什么?

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

long double GiveCx(long double x)
{  
double a = 5.3226927610784935E-01;
double b = 6.5410208763684241E-01;
double c = -1.4312869957125389E+00;
double d = 8.4710834303177074E-01;
return (c*atanl(expl(x-a)/b) + d);
}

double BurkardtCollectionBased_sech_cdf_Offset_model(double x_in)
{
 double temp;
 temp = 0.0;
 // coefficients
 double a = 5.3226927610784935E-01;
 double b = 6.5410208763684241E-01;
 double c = -1.4312869957125389E+00;
 double Offset = 8.4710834303177074E-01;
 temp = c * atan(exp((x_in-a)/b));
 temp += Offset;
 return temp;
}

int main()
{
 int ix;
 for (ix=0; ix<5; ix++)
  printf(" ix = %d ; c = %.20f  ;  %.20Lf \n", ix,      BurkardtCollectionBased_sech_cdf_Offset_model( (long double)ix), GiveCx((long double )ix));
return 0;
}

结果是:

ix = 0; c = 0.25000064588764425721; -0.20004050665796930359

ix = 1; c = -0.75000921765452766010; -0.84455584419096496618

ix = 2; c = -1.24993551212417064455; -1.18701705113792041978

ix = 3; c = -1.36825264215735509232; -1.32186430467910977205

ix = 4; c = -1.39401846938445195256; -1.37195787094497580628

2 个答案:

答案 0 :(得分:4)

您在一个expl(x-a)/b和另一个exp((x_in-a)/b)。检查b是否需要像后一种情况那样划分指数,或者像前一种情况那样划分结果。

您可能需要expl((x-a)/b)中的GiveCx()

答案 1 :(得分:2)

主要问题是ja72状态,但请注意,根据您的编译器,即使函数是均匀化的,您仍然可能会得到略有不同的结果。

http://ideone.com/f29ugQ

  

ix = 0; c = -0.20004050665796929698; -0.20004050665796930359
  ix = 1; c = -0.84455584419096485504; -0.84455584419096496618
  ix = 2; c = -1.18701705113792033153; -1.18701705113792041978
  ix = 3; c = -1.32186430467910986941; -1.32186430467910977205
  ix = 4; c = -1.37195787094497578806; -1.37195787094497580628

原因是doublelong double在没有别名long doubledouble的编译器中的精度和浮点计算的固有不精确性。尽管提供的输入(xx_in除外)具有相同的精度,但您使用的函数执行的计算具有不同的精度(atanlexpl与{{{ 1}}和atan)。 expatanl会将expl输入扩展到double,也可以使用该精度级别执行计算,具体取决于编译器,而long doubleatan应该仅以exp精度执行计算(尽管某些编译器可以选择使计算比输入的类型更精确,因为这仍然可以根据计算得到更准确的结果执行)。

这就是为什么,如果你需要完美的小数精度,你必须使用支持任意数量的小数位的定点库(虽然无理值仍然超出这些能力)。