I have a function that computes a point in 3d spaced based on a value in range [0, 1]
. The problem I\'m facing is, that a binary floating-point number canno
for (t=0; t <= 1.0; t += 0.1) {
your problem is that a binary floating point number cannot exactly represent 0.1
.
The closest 32-bit single precision IEEE754 floating point number is 0.100000001490116119384765625 and the closest 64-bit double precision one 0.1000000000000000055511151231257827021181583404541015625. If the arithmetic is performed strictly at 32-bit precision, the result of adding 0.1f
ten times to 0 is
1.00000011920928955078125
If intermediate computations are performed at greater precision than float
has, it could result in exactly 1.0
or even slightly smaller numbers.
To fix your problem, in this case you could use
for(k = 0; k <= 10; ++k) {
t = k*0.1;
because 10 * 0.1f
is exactly 1.0
.
Another option is to use a small tolerance in your curves_bezier
function,
if (t > 1 && t < 1 + epsilon) {
t = 1;
}
for a suitably small epsilon, maybe float epsilon = 1e-6;
.
When comparing floating point numbers you should check if they are close enough not exactly equal, for the reasons mentioned in other answers, something like:
#define EPSILON 0.000001f
#define FEQUAL(a,b) (fabs((a) - (b)) < EPSILON)
binary floating-point number cannot represent exactly 1
Proof that it can can be found here.
Most accurate representation = 1.0E0
There could be problems with
But 1.0
is none of them!
However 0.1
is a problem case, violating point number 1, look at this:
Most accurate representation = 1.00000001490116119384765625E-1
So if you add up 0.1 ten times, you will get 1.00000001490116119384765625E-0
which is greater than 1.0
.
(examples are in IEEE754 single precision 32 bit floating point numbers)
int i;
for (i=0; i <= 10; i++) {
t=i/10.0;
curves_error error = curves_bezier(points, point, t);
if (error != curves_no_error) {
printf("Error with t = %f.\n", t);
}
else {
printf("t = %f is ok.\n", t);
}
}
This way, the error of the binary format does not get summed up!
(Note: I used extra curly braces for the if
and else
statements. Do that, you'll thank yourself one day.)