https://github.com/veltzer/fcmp
Fcmp is a library to compare two floating point numbers
https://github.com/veltzer/fcmp
Last synced: 6 months ago
JSON representation
Fcmp is a library to compare two floating point numbers
- Host: GitHub
- URL: https://github.com/veltzer/fcmp
- Owner: veltzer
- License: other
- Created: 2012-02-04T21:41:05.000Z (over 13 years ago)
- Default Branch: master
- Last Pushed: 2024-08-29T04:20:08.000Z (10 months ago)
- Last Synced: 2024-08-29T05:35:00.944Z (10 months ago)
- Language: C
- Homepage: https://veltzer.net/fcmp
- Size: 90.8 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README
- Changelog: ChangeLog
- License: LICENSE
- Authors: AUTHORS
Awesome Lists containing this project
README
************************************************************************
fcmp
Copyright (c) 1998-2000 Theodore C. Belding
University of Michigan Center for the Study of Complex Systems
This file is part of the fcmp distribution. fcmp is free software; you
can redistribute and modify it under the terms of the GNU Library
General Public License (LGPL), version 2 or later. This software
comes with absolutely no warranty. See the file COPYING for details
and terms of copying.File: README
Description: README documentation file
************************************************************************FCMP: SAFER COMPARISON OF FLOATING-POINT NUMBERS
It is generally not wise to compare two floating-point values for
exact equality, for example using the C == operator. The fcmp package
implements Knuth's [1] suggestions for safer floating-point comparison
operators as a C function.FCMP HOMEPAGE AND CURRENT RELEASES
The fcmp homepage is at . There you can
always find the current release of fcmp, as well as the fcmp CVS
source code repository, which is available for anonymous read-only
access.To receive announcements of new fcmp releases, you can subscribe to
the fcmp-announce email list by visiting the web page
or by
sending an email to with
the body "subscribe". fcmp-announce is a very low volume list for fcmp
announcements only.REPORTING BUGS
To report a bug in fcmp, visit the fcmp bug tracking system on the web
at or send an email to
(the web page is the preferred
method). Please give full details about the bug, including what fcmp
version, platform, OS, and compiler you used.INSTALLATION
The easiest way to use fcmp is simply to include the source code in
your program. If you are using Windows 95/98, MacOS, or some other
non-Unix platform, this is currently the only available way to use
fcmp.It is also possible to compile and install fcmp as a static or a
shared library on Unix-compatible platforms. See the file INSTALL for
full instructions on how to do this.You can control which versions of the library are compiled and
installed using the configure script. To compile and install only the
static library version of fcmp, run configure with the flag
"--disable-shared". To compile and install only the shared library
version, run configure with the flag "--disable-static". By default,
both static and shared libraries are produced.Note: If you are the system administrator and are installing the
shared library version of fcmp as a system library on a
Unix-compatible platform, then you must make sure that the dynamic
loader can find the shared library at run time. On Linux, you should
add the path of the library's directory to the file /etc/ld.so.conf,
if it is not already present. Then run ldconfig.Similarly, if you installed the shared library version of fcmp in your
home directory, you will have to tell the dynamic loader where to find
the library, since it is not in one of the standard locations. On
Linux, add the path of the directory in which you installed it to your
LD_LIBRARY_PATH environment variable. For example, if you use bash as
your shell and you installed fcmp in ~/local/fcmp in your home
directory, then you should add the following line to your
.bash_profile file:export LD_LIBRARY_PATH=$HOME/local/fcmp/lib:$LD_LIBRARYPATH
USING FCMP
If you have installed the fcmp library, you can use it in your
programs by just including the header file "fcmp.h" and linking your
program with the flag "-lfcmp". You will also have to tell the
compiler where to find the fcmp header file and library, if they are
not already on the compiler's search path. For instance, if you're
using gcc on a Unix-like platform and you installed fcmp in
/usr/local/fcmp:gcc -I/usr/local/fcmp/include -L/usr/local/fcmp/lib foo.c -lfcmp
Of course, if you prefer, you can just include the source code in your
program, rather than using the fcmp libraries.The fcmp function prototype is:
int fcmp(double x1, double x2, double epsilon);
where x1 and x2 are two floating-point numbers to be compared, and
epsilon determines the tolerance of the comparison (see the section
BACKGROUND for details).fcmp returns -1 if x1 is less than x2, 0 if x1 is equal to x2, and 1
if x1 is greater than x2 (relative to the tolerance).For example, the following program should print "the result is: 1"
#include "fcmp.h"
#include
#includeint main() {
int result;
result = fcmp(3.0, 2.0, DBL_EPSILON);
printf("the result is: %d\n", result);
return 0;
}BACKGROUND
Floating point numbers are inherently inexact, and comparisons between
them are also inexact. Equality or `==' comparisons are particularly
unreliable. In the following code snippet, x is unlikely to be
exactly equal to y, even if both variable nominally have the same
value. This is due to sources of error such as truncation error and
rounding error.float x;
float y;/* calculations */
if (x == y) { /* unlikely to work! */
/* code to be executed if x == y */
}For example, the following program (from Priest [3]) may produce the
output "Equal" or "Not Equal", depending on the platform, compiler,
and compile-time options that are used:#include
int main() {
double q;q = 3.0/7.0;
if (q == 3.0/7.0) printf("Equal\n");
else printf("Not Equal\n");
return 0;
}The same problem holds for `<', `>', `<=', `>=', and `!=' comparisons.
Since equality cannot be exactly determined with floating point
numbers, inequality cannot either.What is needed is a comparison operator that takes into account a
certain amount of uncertainty:if (fabs(x - y) <= epsilon) {
/* code to be executed if x == y */
}if (x - y > epsilon) {
/* code to be executed if x > y */
}if (x - y < -epsilon) {
/* code to be executed if x < y */
}In the above code, a neighborhood is defined that extends a distance
epsilon to either side of y on the real number line. If x falls
within epsilon of y, x is declared to be equal to y (the first case,
above). If x is greater than y by an amount that is greater than
epsilon, x is declared to be greater than y (the second case, above).
If x is less than y by an amount that is greater than epsilon, x is
declared to be less than y (the third case, above).The problem then becomes to determine an appropriate value of epsilon.
A fixed value of epsilon would not work for all x and y; epsilon
should be scaled larger or smaller depending on the magnitudes of the
numbers to be compared.A floating point number is represented by two numbers, the significand
(also called the fraction or mantissa) and the exponent, and a sign,
where0 <= significand < 1
and
number = sign * significand * pow(2, exponent).
Knuth's suggestion is to scale epsilon by the exponent of the larger of the
two floating point numbers to be compared:delta = epsilon * maxExponent,
where maxExponent is the exponent of max(x, y). Delta can then be
substituted for epsilon in the code snippets above.The routine fcmp() in this package implements Knuth's comparison
operators. Given a value for epsilon, and two float or double numbers
x and y, it returns 1 if x is determined to be greater than y, 0 if x
equals y, and -1 if x is less than y. (The routine automatically
converts floats to doubles, since there is no single-precision
equivalent for the standard C routines frexp() and ldexp(). However,
it works for both floats and doubles, without modification.)DETERMINING EPSILON
Now that we have found a way to scale epsilon to work with a wide
range of x and y, we still need to choose an appropriate epsilon,
before scaling.If the number of binary digits of error, e, is known, then epsilon
can be calculated as follows:epsilon = (pow(2, e) - 1) * FLT_EPSILON (for floats)
epsilon = (pow(2, e) - 1) * DBL_EPSILON (for doubles)FLT_EPSILON and DBL_EPSILON are equivalent to 1 ulp for single- and
double-precision numbers, respectively; they are defined in the
standard C header file . (An ulp is one unit in the last
place of the significand, or fraction part, of a floating point
number; see Knuth[1] for more details.)TIMING RESULTS
To measure the performance penalty caused by using fcmp() instead
of normal floating-point comparisons such as <, I ran 4 different
benchmarks. In each benchmark except the first, which simply
measured the overhead of the non-comparison portions of the program,
60000000 comparisons were executed. The results are:comparison type total user seconds seconds/comparison
no comparisons 31.55 N/A
< (normal) 35.32 6.28e-8
fcmp 66.36 5.80e-7
fcmp2 66.62 5.85e-7The platform was a 266 MHz Pentium II, running Redhat 5.1 and egcs 1.1
(installed for i386-redhat-linux). All programs were compiled with
-O3. "fcmp2" is a variant of fcmp, where the formulaepsilon * max(fabs(x1), fabs(x2))
is used instead of
epsilon * b^e(max(fabs(x1), fabs(x2)))
In summary, fcmp() is 9.23 times slower than normal floating point
comparisons (<).This may seem like a huge performance hit, but it will not actually
have a major impact on program speed unless fcmp() is used in an
inner loop or another bottleneck within the program. As always, you
should profile your program to see where the bottlenecks are before
attempting to optimize the program by hand for speed.At some point in the future, I hope to make it possible to use fcmp as
a C macro, to avoid the overhead of calling it as a function.BIBLIOGRAPHY
[2] Goldberg, David. (1991). What every computer scientist should know
about floating-point arithmetic. ACM Computing Surveys 23(1): 5-48.
Online at . The online
version includes an addendum by Doug Priest [3].Goldberg, David. (1996). Computer arithmetic. Appendix A in Hennessy,
John L., and David A. Patterson, Computer Architecture: A Quantitative
Approach. Second edition. pp. A1-A77. San Francisco: Morgan
Kaufmann. ISBN 1-55860-329-9.[1] Knuth, Donald E. (1998). The Art of Computer Programming. Volume
2: Seminumerical Algorithms. Third edition. Section 4.2.2,
p. 233. Reading, MA: Addison-Wesley. ISBN 0-201-89684-2.Patterson, David A., and John L. Hennessy. (1998). Arithmetic for
computers. Chapter 4 in Computer Organization and Design: The
Hardware/Software Interface. Second edition. pp. 208-335. San
Francisco: Morgan Kaufmann. ISBN 1-55860-428-6. A more basic
introduction than Goldberg or Knuth.[3] Priest, Doug. (1997). Differences among IEEE 754 implementations.
Addendum to Goldberg's [2] paper. Online at
and
; the latter version
includes Goldberg's [2] paper.Summit, Steve. (1996). C Programming FAQs: Frequently Asked
Questions. Question 14.5, pp. 250-251. Reading, MA:
Addison-Wesley. ISBN 0-201-84519-9. Another algorithm for comparing
floating-point numbers.