Dik said:
Can it? Easily?
Indeed, it was not a true inverse.
Hmm. It is interesting to note that ceil( (x-0.00499995)/c_f)) is
an inverse to round_to_cent(c_f*x). (If there is more than one
possible
inverse the smallest value is chosen). Was the inverse at least
"one sided" (e.g. g(f(x)) == x, even though f(g(x)) is not always
equal to x)?
You think so. Decimal scaling is *not* easy with binary floating point.
Of course it is. Simply divide/multiply by 10.0. Equality constraints
are no harder (or easier). Decimal scaling is only "easy" in binary
fixed point if you are willing to accept slightly strange equality
conditions.
In fixed point the calculations are straightforward, in floating point
there are quite a few surprising subtleties. The formulation you gave
gives correct results. But a slightly different formulation gives wrong
results. You wrote:
if(fmod(dp, 0.01) > 0.00495) {
dp += .01 - fmod(dp, 0.01);
} else {
dp -= fmod(dp, 0.01);
}
changing that only slightly will give a wrong result. Like:
if(fmod(dp, 0.01) > 0.00495) {
dp += .01;
}
dp -= fmod(dp, 0.01);
and I suspect that even the formulation:
f = fmod(dp, 0.01);
if(f > 0.00495) {
dp += .01;
}
dp -= f;
can give wrong results with different inputs.
No, the results may be different (at least if, as usual
and contrary to the C standard (note the desparate try
to get back on topic), extended precision results are not
rounded to double precision before further computation) .
They will not be wrong
(assuming you meant if(f > 0.004995) ). If you make allowance for
the fact that floating point operations are not "exact", you need
not be concerned with the precise nature of the
"error".
It is just those subtleties
about floatin point arithmetic that make doing it in floating point needs
quite a bit of numerical analysis to get it correct.
"Quite a bit" is an exaggeration. Basically, you need to
know the minimum spacing of your problem, and to be
aware that a floating point values may take on a value slightly
abover or below the "true" value.
That is not something
that the programmer of financial programs is equipped with.
We can make provision for naive programmers by using either
a decimal fixed point system, or a very high precision
floating point system (and telling the programmers to use
0.0049999999995 when rounding to the nearest cent,
or better, providing a round_financial() function).
Both solutions incur efficiency cost. Both of the more
efficient binary fixed point, and floating point (using
a native floating point type) require some sophistication
to do correctly (for one thing, both cases require an analysis
to see if a native type is adequate).
In any case, "all my programmers know BASIC and
none of them know C, therefore this problem can be solved in
BASIC but cannot be solved in C" is not much of an argument.
- William Hughes