Categories:

.NET (357)

C (330)

C++ (183)

CSS (84)

DBA (2)

General (7)

HTML (4)

Java (574)

JavaScript (106)

JSP (66)

Oracle (114)

Perl (46)

Perl (1)

PHP (1)

PL/SQL (1)

RSS (51)

Software QA (13)

SQL Server (1)

Windows (1)

XHTML (173)

Other Resources:

What is a good way to check for ``close enough'' floating-point equality?

Q

What is a good way to check for ``close enough'' floating-point equality?

✍: Guest

A

Since the absolute accuracy of floating point values varies, by definition, with their magnitude, the best way of comparing two floating point values is to use an accuracy threshold which is relative to the magnitude of the numbers being compared. Rather than

double a, b;

...

if(a == b) /* WRONG */

use something like

#include <math.h>

if(fabs(a - b) <= epsilon * fabs(a))

where epsilon is a value chosen to set the degree of ``closeness'' (and where you know that a will not be zero). The precise value of epsilon may still have to be chosen with care: its appropriate value may be quite small and related only to the machine's floating-point precision, or it may be larger if the numbers being compared are inherently less accurate or are the results of a chain of calculations which compounds accuracy losses over several steps. (Also, you may have to make the threshold a function of b, or of both a and b.)

A decidedly inferior approach, not generally recommended, would be to use an absolute threshold:

if(fabs(a - b) < 0.001) /* POOR */

Absolute ``fuzz factors'' like 0.001 never seem to work for very long, however. As the numbers being compared change, it's likely that two small numbers that should be taken as different happen to be within 0.001 of each other, or that two large numbers, which should have been treated as equal, differ by more than 0.001 . (And, of course, the problems merely shift around, and do not go away, when the fuzz factor is tweaked to 0.005, or 0.0001, or any other absolute number.)

Doug Gwyn suggests using the following ``relative difference'' function. It returns the relative difference of two real numbers: 0.0 if they are exactly the same, otherwise the ratio of the difference to the larger of the two.

#define Abs(x) ((x) < 0 ? -(x) : (x))

#define Max(a, b) ((a) > (b) ? (a) : (b))

double RelDif(double a, double b)

{

double c = Abs(a);

double d = Abs(b);

d = Max(c, d);

return d == 0.0 ? 0.0 : Abs(a - b) / d;

}

Typical usage is

if(RelDif(a, b) <= TOLERANCE) ...

2015-06-26, 1290👍, 0💬

Popular Posts:

What are the high-level thread states? The high-level thread states are ready, running, waiting, and...

How To Define a Sub Function? - Oracle DBA FAQ - Creating Your Own PL/SQL Procedures and Functions A...

What are database triggers? How are the triggers fired? Read this collection of questions and answer...

Regarding C Coding Given: Line in file Contents 30 int * someIDs, theFirst, *r; 110 someIDs =GetSome...

How To Process Query Result in PL/SQL? - Oracle DBA FAQ - Introduction to PL/SQL You can run queries...