-1

I am trying to evaluate a mathematical expression in C. The expression is a follows : enter image description here

Following is the code that I wrote to evaluate the mathematical expression :

int main()
{  
    
     double x,y,A1,B1,C1,result;

     x = 8.1500e-07;
     y = 7.9714e-08;

     A1 = (1-exp(-2*x))/(2*x);
     B1 = 2/(x*( 1 + pow((y/x),2)) );
     C1 = 1 - ( exp(-x)*( cos(y) - (y/x)*sin(y) ));
    
     result = 1 + A1 - B1*C1;
     
     printf("1 + A1 = %e\n",1+A1);

     printf("B1*C1 = %e\n",B1*C1);

     printf("result = %e\n",result);

     


}

It appears that, when separately evaluated, 1+A1 is evaluated to be equal to B1C1, but 1+A1-B1C1 turns out to be a very small negative value. Here is the result : Outcome of the C program shown above. I want to know whether I can regard this to be as some error in computation in analogy with error in experiment and safely consider the result to be zero ? Or, am I missing something ?

bubucodex
  • 109
  • 6
  • 4
    Does this answer your question? [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Gerhardh Apr 06 '23 at 06:51
  • Notice that`%e`, by default, prints 6 decimals. If you crank up the precision, you will notice that the two terms are actually slightly different, which explains the non-zero difference. Now, whether that difference is an actual, mathematic, difference or an artifact of floating-point errors (as pointed out by Gerhardh in an other comment), I am too lazy to even try to find out. – Ture Pålsson Apr 06 '23 at 07:11
  • Can you comment on how can I find that whether this is actually a mathematical difference ?@TurePålsson – bubucodex Apr 06 '23 at 07:17
  • 2
    You could increase accuracy of the floating point calculations by replacing 1-exp(X) with -expm1(X). – Ian Abbott Apr 06 '23 at 07:37
  • You could also replace `1 + A1 - B1*C1` with `fma(-B1, C1, 1 + A1)` for a tiny improvement in accuracy. – Ian Abbott Apr 06 '23 at 09:13
  • Shouldn't C(x) be C(x,y) since there are two variables? I cannot guess how close (x, y) = (8.1500e-07, 7.9714e-08) is to an actual, mathematical root of the function, but any nearby actual mathematical root is likely to be irrational. Also, the variables `x` and `y` will store an inexact approximation of the constants as written in the source code, and the floating point results will be an approximation of the mathematical result. So all in all, it is unlikely that you will end up with a result of exactly zero. – Ian Abbott Apr 06 '23 at 09:20
  • @IanAbbott Actually, I have considered y as a constant and x as a variable. By keeping y fixed I wanted to see the limiting behavior of the function C(x) as x tends to zero. Mathematically, is this limit zero ? I think you are correct in that x = 8.1500e-07, is not the exact solution of the equation C(x) = 0. Although C(x) should be zero in the limit x tends to zero( I am assuming this is true ), in computer calculations it is not exactly zero. – bubucodex Apr 06 '23 at 10:16
  • I guess you would need to try L'Hôpital's rule to find the limit as x approaches zero. – Ian Abbott Apr 06 '23 at 10:31
  • @IanAbbott Right – bubucodex Apr 06 '23 at 10:50
  • @Gerhardh: No, this is not a duplicate of that question. The values of `1+A1` and `B1*C1` are in fact different even if computed with infinite precision, even if that result is then rounded to the common `double` format. So there is no illusion of equality produced by floating-point arithmetic. The fact that equal numerals were printed for them is solely an artifact of the output format, not of the floating-point format or arithmetic. Please do not promiscuously mark floating-point questions as duplicates of that question. The actual issue present in a question should be considered. – Eric Postpischil Apr 06 '23 at 12:32

1 Answers1

3

That values are the same to the 6th decimal digit doesn't mean they are the same.

 printf("1 +A1 = %.20e\n",1+A1);
 printf("B1*C1 = %.20e\n",B1*C1);

prints:

1 +A1 = 1.99999918502629325801e+00
B1*C1 = 1.99999918503684992466e+00
KamilCuk
  • 120,984
  • 8
  • 59
  • 111