On Mar 13, 10:05 am, "Alexander Stoyakin" <s...@ua.fmwrote:

Hello,

please advise on the following issue. I need to check that difference

between two double values is not higher than defined limit.

int main()

{

double limit = 0.3;

double val1 = 0.5, val2 = 0.2;

if ( (val1 - val2) limit )

puts("Difference higher than limit!");

return 0;

}

This program displays message due to undefined binary presentation of

double, so result is unexpected. I see that it is behavior by

standard. But what can I do to make this code work as expected, i.e.

treat 0.3 as 0.3, not as (for example) 0.3000000000000000012? Are

there any standard ways (macros, functions) to fix the precision for

double integers? Everything I found is just formatting for input-

output functions, but it doesn't affect the binary presentation, just

visualisation.

The type of double is not integral unless you store integers in it.

It is floating point (which is really a base 2 fractional

representation internally).

Typically, numbers like 0.3 and 1.7 cannot be stored as exact values

in floating point representation.

Here is a very good document that explains floating point in html

format:

http://docs.sun.com/source/806-3568/ncg_goldberg.html
Here is the same thing as a PDF file:

http://cch.loria.fr/documentation/IE...M/goldberg.pdf
Related information from the C-FAQ:

14.1: When I set a float variable to, say, 3.1, why is printf printing

it as 3.0999999?

A: Most computers use base 2 for floating-point numbers as well as

for integers. In base 2, one divided by ten is an infinitely-

repeating fraction (0.0001100110011...), so fractions such as

3.1 (which look like they can be exactly represented in decimal)

cannot be represented exactly in binary. Depending on how

carefully your compiler's binary/decimal conversion routines

(such as those used by printf) have been written, you may see

discrepancies when numbers (especially low-precision floats) not

exactly representable in base 2 are assigned or read in and then

printed (i.e. converted from base 10 to base 2 and back again).

See also question 14.6.

4.4: My floating-point calculations are acting strangely and giving

me different answers on different machines.

A: First, see question 14.2 above.

If the problem isn't that simple, recall that digital computers

usually use floating-point formats which provide a close but by

no means exact simulation of real number arithmetic. Underflow,

cumulative precision loss, and other anomalies are often

troublesome.

Don't assume that floating-point results will be exact, and

especially don't assume that floating-point values can be

compared for equality. (Don't throw haphazard "fuzz factors"

in, either; see question 14.5.)

These problems are no worse for C than they are for any other

computer language. Certain aspects of floating-point are

usually defined as "however the processor does them" (see also

question 11.34), otherwise a compiler for a machine without the

"right" model would have to do prohibitively expensive

emulations.

This article cannot begin to list the pitfalls associated with,

and workarounds appropriate for, floating-point work. A good

numerical programming text should cover the basics; see also the

references below.

References: Kernighan and Plauger, _The Elements of Programming

Style_ Sec. 6 pp. 115-8; Knuth, Volume 2 chapter 4; David

Goldberg, "What Every Computer Scientist Should Know about

Floating-Point Arithmetic".

14.5: What's a good way to check for "close enough" floating-point

equality?

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))

for some suitably-chosen degree of closeness epsilon (as long as

a is nonzero!).

References: Knuth Sec. 4.2.2 pp. 217-8.

14.6: How do I round numbers?

A: The simplest and most straightforward way is with code like

(int)(x + 0.5)

This technique won't work properly for negative numbers,

though (for which you could use something like

(int)(x < 0 ? x - 0.5 : x + 0.5)).