apfloat
#include <iostream> #include "apfloat.h" using namespace std; int main(int argc, char *argv[]) { apfloat a = 2.0, b = 1.0, c = 0.5, d = 1e-13; cout << pretty << a << endl; cout << pretty << b << endl; cout << pretty << c << endl; cout << pretty << d << endl; return 0; }You might get an output like:
2 1 0.500000000000000059 0.000000000000100000000000000014551915In fact, any of the three first lines output can be "incorrect", and the last line output is almost certainly "incorrect".
Why this happens is because numbers like 1e-13
can't be presented exactly in radix-2, which
is the radix used by double type of numbers. When the double (e.g. 1e-13
) is converted
to radix-10, the result is not exactly the same as the original number. Thus any apfloat constructed
from a double might not be correct to more than about 16 digits (in radix-10), the accuracy
of a double.
Furthermore, it's important to realize that this applies to apfloats constructed from any
double, even if the double could be presented exactly in radix-2 (like 0.5
). This is
because of performance reasons. The apfloat constructor accepting a double doesn't consider special
cases like this, and it simply can always produce a number with a relative error of about 10-16.
Also, if the radix used by apfloat is not 10, then a number like 0.5
might not be
possible to present exactly anyway (for example, in radix-7, 1/2 is 0.333...). Also, the internal
representation of doubles is completely dependent on the computer platform and compiler used
(nothing guarantees that e.g. IEEE formats are used), so any attempt to e.g. handle a number
like 0.5
accurately for radix-10 would probably still be futile.
The obvious workaround is to use the constructor taking a string, which guarantees that the digits your number will have are exactly the same ones that you specify. For example:
apfloat x("0.5", 1000);
Note that the headers were changed from the "old style" to the "new style" in apfloat v. 2.40. You can still use apfloat v. 2.35 if you have a compiler that doesn't support the STL.
int truncate (const char *filename, long long size);
Often, many of the gcc versions early in a branch (like 3.0.0 or 3.0.1) have bugs that prevent using them with apfloat. The latest versions in a branch (like 2.95.3 or 3.2.3) usually work much better.
With other compilers you often can get the compiler to crash with an internal error.
Try reducing or removing the optimization options from the OPTS parameter in the makefile. For djgpp/gcc you minimally need only "OPTS = -w" to compile apfloat; however this results in quite unoptimized code. It should be most robust, though (no optimization is done, only all compilation warning messages are disabled). You can try to compile manually some of the apfloat source files with heavier optimization options and see at which point your program stops working. With gcc a good starting point is to try -O2 instead of -O3.
See also the "Known problems with gcc" section.
Some versions of various compilers and operating systems are apparently buggy and this may actually cause your program to crash. Some instability is known to exist e.g. with the Linux kernel version 2.0.0 and various versions of the gcc / djgpp compilers. See the "Known problems with gcc" section.
The WFTA executables compile and work properly only with the 32-bit versions of apfloat (possibly only those which are based on the Intel x86 platform).
The WFTA is not used at all in the apfloat library, it was an early experiment and it is not really supported anymore. Experiment at your own risk.
Last updated: May 6th, 2004