# Approximation of error-function erf(x)

The code beyond approximates the error-function erf(x) with following formular $erf(x)=1-(a_1t+a_2t^2+a_3t^3)e^{-x^2})$ for $x\geq0$ inclusive the identity $erf(-x)=-erf(x)$.

1. Is it okay to end the program in the middle of a code with exit(EXIT_FAILURE)? I just tried to avoid it and came to following solution, where the program always ends with return 0 at the end of the main-programm: https://codepaste.net/ek8ed5 So the question is whats's the more correct way?

(I hope a moderator can paste this code section in here please, because somehow I didn't make it work to show it as nicely formatted code, sorry!)

1. What else can I improve?

.

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

#define p 0.47047
#define a_1 0.3480242
#define a_2 -0.0958798
#define a_3 0.7478556

double ErrorFunction(double x);

int main(void)
{
double x = 0;

do
{
printf("Enter any value x to show erf(x): ");

if (scanf_s("%lf", &x) != 1)
{
printf("error: invalid input\n");
exit(EXIT_FAILURE);
}
else
{
printf("\n erf(x)=%f\n\n", ErrorFunction(x));
}

} while (x != 0);

return 0;
}

double ErrorFunction(double x)
{
double t = 0;

if (x < 0)
{
x = -x;
t = 1 / (1 + p*x);
return -(1 - (a_1*t + a_2*t*t + a_3*t*t*t)*exp(-(x*x)));
}
else
{
t = 1 / (1 + p*x);
return 1 - (a_1*t + a_2*t*t + a_3*t*t*t)*exp(-(x*x));
}
}


• DRY. Actual computations are repeated twice, which is always a signal for improvement:

if (x < 0) {
t = 1 / (1 - p*x);
} else {
t = 1 / (1 + p*x);
}

result = compute_the_formula(t, x);

if (x < 0) {
result = -result;
}
return result;

• Try to cut down multiplications. Instead of

a_1*t + a_2*t*t + a_3*t*t*t


consider

t*(a_1 + t*(a2 + t*a_3)))


Three multiplications instead of original six is not only faster, but generally more accurate.

• Thanks. 1. Actually I should really implement erf(-x)=-erf(x) according to this exercise. And it is also called identity. – physics Apr 18 '17 at 7:37
• 2. I.e. the less multiplications you have the more accurate it is, because you have less rounding errors? – physics Apr 18 '17 at 7:44
• 3. What do you say to my v1- and v2-main() in my starting post (codepaste.net)? – physics Apr 18 '17 at 7:44
double ErrorFunction(double x);


Would erf be a better name?

    if (scanf_s("%lf", &x) != 1)

      printf("\n erf(x)=%f\n\n", ErrorFunction(x));


Why the inconsistency between %lf and %f?

Actually I should really implement erf(-x)=-erf(x) according to this exercise

The best way to do that from the point of view of 1) self-documenting code; 2) not accidentally breaking it in maintenance is

double ErrorFunction(double x)
{
if (x < 0) return -ErrorFunction(-x);
...

• Oh yeah that is good idea! So I only have one code line that computes my approximation instead ot two! 1. I didn't use erf as name, because I got this compiler warning: docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/… or is it ok to ignore this one? I thought that you always should avoid any compiler Warnings. (I use VS 2017) – physics Apr 18 '17 at 10:11
• 2. I used %fin my printf, because it makes no difference to %lfby using it in a printf and I got the advice from here too: codereview.stackexchange.com/questions/160846/… (point 5) – physics Apr 18 '17 at 10:16
• And when are you trying to use it on 'scanf' it won't work, because pointers aren't promoted to anything, but variables are. (stackoverflow.com/questions/210590/…) But I guess i should always stick to the same %? I. e. %lffor doubles, %ffor floats etc. – physics Apr 18 '17 at 10:17
• @physics, 1. Makes sense that the logical name is already used. Still, I'd favour namespacing the name. In extremis, my_erf. 2. Fair enough. Gareth knows C better than I do. – Peter Taylor Apr 18 '17 at 10:25