Floats and doubles can be NaN
NaN = Not a number.
You may want to read this: How to use nan and inf in C?
https://en.wikipedia.org/wiki/NaN
Set errno
Not all functions return floating point values, so NaN can't always be used.
Since some math functions can return any number of their type, you can't really use the return value to indicate that an error has occurred.
You could still unset and set errno
. It does have the side effect that old values of errno
will be overwritten.
In example.h:
#include <errno.h>
/* extern int errno; */
double division(double n, double d);
In example.c:
#include "example.h"
double division(double n, double d)
{
if (0 == d)
{
errno = EDOM;
return 0.0; /* Does not matter. */
}
else
return n/d;
}
In main.c:
#include <stdio.h>
#include "example.h"
int main(int argc, char *argv[])
{
division(1.0, 0.0);
if (EDOM == errno)
{
fprintf(stderr, "Couldn't divide 1.0 by 0.0\n");
errno = 0; /* Reset so it won't appear that the error has
occurred even when it hasn't. */
}
division(3.14, 2.78);
if (EDOM == errno)
{
fprintf(stderr, "Couldn't divide 3.14 by 2.78.\n");
errno = 0;
}
return 0;
}
Set an error flag
Or you could use a global variable of your own that you don't unset if no error has occured.
This would allow you to make a whole bunch of calls to these functions and only check for error once.
In example.h:
int error_flag = 0; /* Set to non-zero value on error. */
double division(double n, double d);
In example.c:
#include "example.h"
double division(double n, double d)
{
if (0 == d)
{
error_flag = 1;
return 0.0;
} else
return n/d;
}
In main.c:
#include <stdio.h>
#include "example.h"
int main(int argc, char *argv[])
{
double x;
error_flag = 0; /* External variable */
x = division(division(3.14, 1.3 - division(3.9, -3.0)), 7);
if (error_flag)
{
/* The last call to division() didn't unset error_flag. */
fprintf(stderr, "Something went wrong.\n");
return 1;
}
/* Not reached. */
printf("%f\n", x);
return 0;
}
Math domain errors can be avoided
Sometimes.
Or don't do anything to handle math errors.
If you try to open a file, it's difficult to predict the outcome, because knowing just the filename isn't enough; you'll have to check whether or not the file even exists and if it does exist you'll have to check the permissions.
Math (as I know it) isn't that difficult, you only need to know the arguments. Consider `f(x) = 1/x`: you only need to know the value of `x` to determine if the call to `f` will fail or not, and this well known function is well known to be defined for `x != 0`.
One liner: `double division(double n, double d) {return n/d;}`
(Proved myself wrong about that. Ex: f(a, b) = 1/(a+b)
)