473,320 Members | 2,054 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

operations with double integers

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.

Thank you in advance.

Mar 13 '07 #1
6 2890
Alexander Stoyakin wrote:
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.

Thank you in advance.
Floating-point maths is one place C99 has made improvements. If your
implementation is at least partially C99 compliant, you might want to
see if you can use the is* macros in math.h. In this particular case
the isgreater macro can be used like so:

if(isgreater(diff, 0.3)) /* ... */

Otherwise, you should allow for a small delta around the value you're
comparing to.

Mar 13 '07 #2
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)).

Mar 13 '07 #3
"santosh" <sa*********@gmail.comwrites:
Alexander Stoyakin wrote:
>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.
Floating-point maths is one place C99 has made improvements. If your
implementation is at least partially C99 compliant, you might want to
see if you can use the is* macros in math.h. In this particular case
the isgreater macro can be used like so:

if(isgreater(diff, 0.3)) /* ... */
The only difference between the isgreater() macro and the built-in ">"
operator is it behavior in the presence of NaNs, which doesn't help at
all in this case.
Otherwise, you should allow for a small delta around the value you're
comparing to.
See user923005's followup for more information.

The phrase "double integer" is incorrect; double is a floating-point
type, not an integer type.

If you want to represent values like 0.3 exactly, you might consider
using scaled integers. For example, you might use the integer 3 to
represent the real value 0.3. All the code that works with these
values will then have to allow for the scaling factor. One example of
this kind of thing is treating a quantity of money as an integer
number of cents rather than a floating-point number of dollars (or
whatever your local currency is).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 13 '07 #4
Keith Thompson wrote:
"santosh" <sa*********@gmail.comwrites:
Alexander Stoyakin wrote:
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.
[ ... ]
Floating-point maths is one place C99 has made improvements. If your
implementation is at least partially C99 compliant, you might want to
see if you can use the is* macros in math.h. In this particular case
the isgreater macro can be used like so:

if(isgreater(diff, 0.3)) /* ... */

The only difference between the isgreater() macro and the built-in ">"
operator is it behavior in the presence of NaNs, which doesn't help at
all in this case.
Thanks for the correction.

<snip>

Mar 13 '07 #5
On Mar 13, 5:05 pm, "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.
You first have to figure out what exactly you want. If val1 was 0.5 +
1e-12, would you want the answer "greater" or not?

It seems that "is val1 minus val2 greater than limit"? is not the
question you want to answer, so you must have a different question. .
Maybe your question is "If I printed val1 with two decimal digits, and
printed val2 with two decimal digits, would the printed result look as
if val1 - val2 is greater than 0.2"? If that was your question, you
would check whether floor (100 * val1 + 0.5) - floor (100 * val2 +
0.5) 20.0. Maybe your question is "is val1 - val2 so large that I am
sure the difference would be greater than 0.2, even if I had used more
precision"? In that case you have to check how val1 and val2 were
calculated, what rounding errors you could have made, and check if the
difference is greater than 0.2 plus any possible rounding errors added
up.

If you choose a small constant k, maybe k = 10, and check whether val1
- val2 limit + k * DBL_EPSILON + max (|val1|, |val2|. |limit|), then
it is relatively likely that you get the right result. Depends how
val1, val2, limit have been calculated.

Mar 13 '07 #6
Alexander Stoyakin wrote:
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.
It's more fundamental than that.

In base 2, both 0.2 and 0.3 are repeating fractions.

0.2 decimal = 0.001100 1100 1100 1100 ... binary
0.3 decimal = 0.010011 0011 0011 0011 ... binary

This is true, in fact, for *every* decimal fraction that doesn't end in
the digit 5 (and for some that do). No finite amount of precision is
enough to represent them exactly.
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?
Using the information supplied in other answers, you have to either
design a test more sophisticated than

(val1 - val2) limit

or represent val1, val2, and limit as something other than a double
with a fractional part.

- Ernie http://home.comcast.net/~erniew
Mar 14 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: jose luis fernandez diaz | last post by:
Hi, My OS is: cronos:jdiaz:tmp>uname -a HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license I compile in 64-bits mode the program below:
21
by: Morten Aune Lyrstad | last post by:
I wish to create my own assembly language for script. For now it is mostly for fun and for the sake of the learning, but I am also creating a game engine where I want this system in. Once the...
4
by: Xarky | last post by:
Hi, I am trying to work out the following equation double x; x = 2/40; The value of x being reported is 0; The real answer should be 0.05. Can someone explain me why this occurs and how I...
21
by: ashish.sadanandan | last post by:
Hi, I haven't done a lot of C++ programming (done a lot of it in C) and the reason why I'm considering switching now is also the question I'm posting here. I have some library functions that...
11
by: Bo Peng | last post by:
Dear C++ experts, I need to store and retrieve a meta information that can be int or double. The program would be significantly simpler if I can handle two types uniformly. Right now, I am using...
4
by: alex | last post by:
hi friends ... i am facing a problem while detecting floating point operations in my project, please help me. i want to find out the places in my C/C++ project where i am doing floating...
6
by: Johs | last post by:
I have: int a = 1; int b = 2; double c = a/b; Is it somehow possible to divide these two integers and get the result as a double 0.5? Or do they both have to be declared as doubles?
4
by: siryuhan | last post by:
I am trying to apply bitwise operations on float, double, and long double values. I do not believe this is possible natively, so I created a wrapper class to construct a double value given two...
22
by: Bill Reid | last post by:
I just noticed that my "improved" version of sscanf() doesn't assign floating point numbers properly if the variable assigned to is declared as a "float" rather than a "double". (This never...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.