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)\$.
- 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 withreturn 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!)
- 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));
}
}
2 Answers 2
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.
-
\$\begingroup\$ Thanks. 1. Actually I should really implement
erf(-x)=-erf(x)
according to this exercise. And it is also called identity. \$\endgroup\$physics– physics2017年04月18日 07:37:09 +00:00Commented 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\$physics– physics2017年04月18日 07:44:15 +00:00Commented 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\$physics– physics2017年04月18日 07:44:18 +00:00Commented Apr 18, 2017 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
?
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);
...
-
\$\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\$physics– physics2017年04月18日 10:11:09 +00:00Commented Apr 18, 2017 at 10:11 -
\$\begingroup\$ 2. I used
%f
in my printf, because it makes no difference to%lf
by using it in aprintf
and I got the advice from here too: codereview.stackexchange.com/questions/160846/… (point 5) \$\endgroup\$physics– physics2017年04月18日 10:16:39 +00:00Commented 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.%lf
for doubles,%f
for floats etc. \$\endgroup\$physics– physics2017年04月18日 10:17:09 +00:00Commented 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\$Peter Taylor– Peter Taylor2017年04月18日 10:25:46 +00:00Commented Apr 18, 2017 at 10:25