2
\$\begingroup\$

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));
 }
}
vnp
58.6k4 gold badges55 silver badges144 bronze badges
asked Apr 17, 2017 at 19:57
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$
  • 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.

answered Apr 17, 2017 at 22:01
\$\endgroup\$
3
  • \$\begingroup\$ Thanks. 1. Actually I should really implement erf(-x)=-erf(x) according to this exercise. And it is also called identity. \$\endgroup\$ Commented Apr 18, 2017 at 7:37
  • \$\begingroup\$ 2. I.e. the less multiplications you have the more accurate it is, because you have less rounding errors? \$\endgroup\$ Commented Apr 18, 2017 at 7:44
  • \$\begingroup\$ 3. What do you say to my v1- and v2-main() in my starting post (codepaste.net)? \$\endgroup\$ Commented Apr 18, 2017 at 7:44
2
\$\begingroup\$
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?


Following up on a comment you made to another answer:

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);
 ...
answered Apr 18, 2017 at 8:23
\$\endgroup\$
4
  • \$\begingroup\$ 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) \$\endgroup\$ Commented Apr 18, 2017 at 10:11
  • \$\begingroup\$ 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) \$\endgroup\$ Commented Apr 18, 2017 at 10:16
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Apr 18, 2017 at 10:17
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Apr 18, 2017 at 10:25

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.