473,321 Members | 1,748 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,321 software developers and data experts.

C sucks at math? (help)

I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
..0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

Any help or tips are greatly appreciated!

Jun 27 '06 #1
38 2476
Jordi wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
..0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

It doesn't, the floating point hardware or emulation does.

Floating point isn't precise. Avoid floats and use doubles, even then,
you have to understand the limitations of floating point math.

You must have a dodgy FPU, the result is 45.400000 on my system :)

--
Ian Collins.
Jun 27 '06 #2
In article <11*********************@i40g2000cwc.googlegroups. com>,
Jordi <jb*****@gmail.com> wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002 Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}


Your program uses undefined behaviour: you do not have a prototype
for printf() in scope.

[Admittedly, fixing that probably won't solve your difficulty ;-) ]
--
"It is important to remember that when it comes to law, computers
never make copies, only human beings make copies. Computers are given
commands, not permission. Only people can be given permission."
-- Brad Templeton
Jun 27 '06 #3
Thanks for your reply!

I had just figured out that the emulation/casting was where it went
wrong and I was about to post it. I would probably not have thought of
using doubles anytime soon though (I thought they didn't exist in C and
that they were introduced with C++, which I normally use, or something,
thank God I'm wrong :P).
It seems that doubles work for the toy-program, so they probably will
for the entire project, but it's kind of big so I won't be altering it
right now (it's 2:36 am here).

By the way, I'm using an SSH program to log in on some old Macintosh
computer where the software is running, so that could probably be
considered 'dodgy'. :)

Anyway, thanks!
Ian Collins wrote:
Jordi wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
..0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

It doesn't, the floating point hardware or emulation does.

Floating point isn't precise. Avoid floats and use doubles, even then,
you have to understand the limitations of floating point math.

You must have a dodgy FPU, the result is 45.400000 on my system :)

--
Ian Collins.


Jun 27 '06 #4
see the attached link for an explanation on floating point numbers and why
they can be inaccurate. Simple answer is, blame your machine not the
compiler (because it usually the underlying machine code doing the floating
point work and making the "mistake")...

http://www.answers.com/topic/floating-point

go to the section titled "Problems with floating-point" for a detailed
reason...

"Jordi" <jb*****@gmail.com> wrote in message
news:11*********************@i40g2000cwc.googlegro ups.com...
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
.0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

Any help or tips are greatly appreciated!

Jun 27 '06 #5
>I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002
There is no exact representation of most decimal numbers in binary
floating point. Float only claims to have 6 digits, and your output
is off by 2 counts in the 8th digit. You have little cause to complain
that you didn't get the accuracy advertised.

45.4 as float:
Before: 45.39999771118164062500000000000000000000000000000 0000000000000
Value: 45.40000152587890625000000000000000000000000000000 0000000000000
After: 45.40000534057617187500000000000000000000000000000 0000000000000

The three choices are shown above. The value you got was the closest
possible representation of the mathematically correct answer in an
IEEE 32-bit floating point number.
Obviously, the output should be 45.4 (or 45.400000), but for some
There is no such number exactly representable in binary floating point.
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.
Then use a more precise floating-point value, like double or long double.
(That's just putting off the problem, though).
* It seems that it is not .000002 is added, but rather
.0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?


Use floating-point hardware with an infinite number of bits. Or,
if that's too expensive, just use MORE bits.

Gordon L. Burditt
Jun 27 '06 #6
I said I wouldn't try doubles in the real project, but it didn't prove
that difficult and I couldn't let it rest. Anyway, it didn't work as
well as I hoped. This is some of the output I got:
x = 64.200000 / (107.000000 / 5) = 64.200000 / 21.400000 = 3.000000 = 2

Notice the 3.000000 = 2? That's what's screwing my program over.

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy. That's probably not going to happen anytime soon, so I need
another solution. Is there a way to make the program use the calculated
3.000000 instead of the 2.9999999999999999999999999 it actually
calculated? Is there some way to specify how accurate I need things?

Thanks for any help!

Ian Collins wrote:
Jordi wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
..0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

It doesn't, the floating point hardware or emulation does.

Floating point isn't precise. Avoid floats and use doubles, even then,
you have to understand the limitations of floating point math.

You must have a dodgy FPU, the result is 45.400000 on my system :)

--
Ian Collins.


Jun 27 '06 #7
"Jordi" <jb*****@gmail.com> writes:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
.0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?


The comp.lang.c FAQ is at <http://www.c-faq.com/>. You've asked
question 14.1.

--
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.
Jun 27 '06 #8
>I said I wouldn't try doubles in the real project, but it didn't prove
that difficult and I couldn't let it rest. Anyway, it didn't work as
well as I hoped. This is some of the output I got:
x = 64.200000 / (107.000000 / 5) = 64.200000 / 21.400000 = 3.000000 = 2

Notice the 3.000000 = 2? That's what's screwing my program over.

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy. That's probably not going to happen anytime soon, so I need
another solution. Is there a way to make the program use the calculated
3.000000 instead of the 2.9999999999999999999999999 it actually
calculated? Is there some way to specify how accurate I need things?


Round it instead of truncating?

This is commonly done with
floor(x + 0.5)

You might also find it appropriate to use a small fudge factor (e.g. 0.01)
rather than doing normal rounding.

Gordon L. Burditt
Jun 27 '06 #9
Jordi wrote:

I said I wouldn't try doubles in the real project,


doubles are for ordinary floating point calculations.
The type of (0.0), is double.
The %f format specifier for printf, is for type double.
The default argument promotions,
promote float types to type double.

Use float when you want the smallest float type.
(0.0f) is of type float.

Use long double when you want
the float type with the greatest range in C89.

--
pete
Jun 27 '06 #10
In article <11*********************@m73g2000cwd.googlegroups. com>,
Jordi <jb*****@gmail.com> wrote:
I said I wouldn't try doubles in the real project, but it didn't prove
that difficult and I couldn't let it rest. Anyway, it didn't work as
well as I hoped. This is some of the output I got:
x = 64.200000 / (107.000000 / 5) = 64.200000 / 21.400000 = 3.000000 = 2 Notice the 3.000000 = 2? That's what's screwing my program over.
It looks to me as if you are doing an integer truncation of the value
that is approximately 3. If so, then you should consider rounding
the value instead.
Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy.
Yes, pretty much so.
That's probably not going to happen anytime soon, so I need
another solution. Is there a way to make the program use the calculated
3.000000 instead of the 2.9999999999999999999999999 it actually
calculated? Is there some way to specify how accurate I need things?


No, you cannot specify the accuracy.

Usually for problems such as this, you should do a numeric analysis
of the algorithm to figure out how to maximize the precision.

For any algorithm, there will be a maximum precision you could possibly
obtain by using double and carefully re-arranging the calculations.
If that precision is not enough, then you could consider using one
of the indefinite precision calculation libraries that are available
from various sources. Those libraries are not good substitutes for
realizing that, for example, 64.2 is not exactly representable in
standard binary floating point numbers, but sometimes the calculations
can be rejigged with rational numbers -- for example,
instead of 64.2, perhaps you could use 642/10 and a
rational- calculation package and only convert to floating point in the
final step.
--
Prototypes are supertypes of their clones. -- maplesoft
Jun 27 '06 #11
Jordi wrote:
I said I wouldn't try doubles in the real project, but it didn't prove
that difficult and I couldn't let it rest. Anyway, it didn't work as
well as I hoped. This is some of the output I got:
x = 64.200000 / (107.000000 / 5) = 64.200000 / 21.400000 = 3.000000 = 2

Notice the 3.000000 = 2? That's what's screwing my program over.

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy. That's probably not going to happen anytime soon, so I need
another solution. Is there a way to make the program use the calculated
3.000000 instead of the 2.9999999999999999999999999 it actually
calculated? Is there some way to specify how accurate I need things?

Thanks for any help!

Ian Collins wrote:
Jordi wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
..0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

It doesn't, the floating point hardware or emulation does.

Floating point isn't precise. Avoid floats and use doubles, even then,
you have to understand the limitations of floating point math.

You must have a dodgy FPU, the result is 45.400000 on my system :)

--
Ian Collins.


Eww, top posting.

What you need to do is figure out what degree of precision you need, and
after all of the calculations, perform your fix. See, your remark on 3.0
being equal to 2 makes me think you used a floor function in there
somewheres. Instead, use floor(x+0.5) to round to the nearest. Same if
use used and (int) cast. At any rate, this isn't C's fault, it's the
fault of IEEE's float specification, that says that you only need 32
bits of precision, instead of infinity.

Inmatarian.
Jun 27 '06 #12

Jordi wrote:

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy.


Infinitely many bits doesn't give you "100% accuracy". You will
only be able to represent the algebraic numbers. If you
select a Real number at random, it will be transcendental
with probability 1, so you will be unable to represent nearly all
of them. (My Real Analysis is rusty, but I'm pretty sure
the algebraic numbers have measure 0, and less certain
that they are all representable with infinitely long binary
strings.)

In short, it's not C, nor the computer that is causing problems
here. It's the nature of mathematics. :)

Jun 27 '06 #13
"Bill Pursell" <bi**********@gmail.com> writes:
Jordi wrote:

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy.


Infinitely many bits doesn't give you "100% accuracy". You will
only be able to represent the algebraic numbers.

[...]

Sure, if you use one of those old-fashioned implementations that only
has aleph-null-bit floating-point. Any decent modern implementation
should provide at least aleph-one bits.

We should be getting the first computational results any eon now.

--
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.
Jun 27 '06 #14
In article <11**********************@i40g2000cwc.googlegroups .com> "Bill Pursell" <bi**********@gmail.com> writes:

Jordi wrote:

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy.


Infinitely many bits doesn't give you "100% accuracy". You will
only be able to represent the algebraic numbers. If you
select a Real number at random, it will be transcendental
with probability 1, so you will be unable to represent nearly all
of them. (My Real Analysis is rusty, but I'm pretty sure
the algebraic numbers have measure 0, and less certain
that they are all representable with infinitely long binary
strings.)


Yup, definitely rusty. All real numbers are representable in infinitely
many bits.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jun 27 '06 #15
In article <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> writes:
"Bill Pursell" <bi**********@gmail.com> writes:
Jordi wrote:

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy.


Infinitely many bits doesn't give you "100% accuracy". You will
only be able to represent the algebraic numbers.

[...]

Sure, if you use one of those old-fashioned implementations that only
has aleph-null-bit floating-point.


But than you can also represent all transcendental numbers.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jun 27 '06 #16
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
"Bill Pursell" <bi**********@gmail.com> writes:
Infinitely many bits doesn't give you "100% accuracy". You will
only be able to represent the algebraic numbers.

No, that would be true for finite but arbitrarily long bit strings.
If you can have infinitely long strings, you can represent all the
reals. You may need a better editor to type in the initialiser
though.
Any decent modern implementation
should provide at least aleph-one bits.


Doesn't that have bit-order problems?

-- Richard
Jun 27 '06 #17
"Jordi" <jb*****@gmail.com> writes:
I said I wouldn't try doubles in the real project, but it didn't prove
that difficult and I couldn't let it rest. Anyway, it didn't work as
well as I hoped. This is some of the output I got:
x = 64.200000 / (107.000000 / 5) = 64.200000 / 21.400000 = 3.000000 = 2

Notice the 3.000000 = 2? That's what's screwing my program over.

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy. That's probably not going to happen anytime soon, so I need
another solution. Is there a way to make the program use the calculated
3.000000 instead of the 2.9999999999999999999999999 it actually
calculated? Is there some way to specify how accurate I need things?


See "What Every Computer Scientist Should Know About Floating-Point
Arithmetic" by David Goldberg:

http://www.weblearn.hs-bremen.de/ris...s/goldberg.pdf
For comparing floating point values, I recommend

fabs(a-b) < tolerance

where you get to pick 'tolerance' based on your problem. fabs() is
for double, fabsf() for float.

-Peter
Jun 27 '06 #18
In article <e7**********@pc-news.cogsci.ed.ac.uk> ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
"Bill Pursell" <bi**********@gmail.com> writes:
Infinitely many bits doesn't give you "100% accuracy". You will
only be able to represent the algebraic numbers.


No, that would be true for finite but arbitrarily long bit strings.


And that is also false. Finite but arbitrarily long bit strings give
you only a subset of the rational numbers.

Rational numbers have either a finite representation or a representation
that will ultimately repeat (if the denominator is not a power of 2).
From the representation you can not distinguish irrational algebraic
numbers and transcendental numbers. But I think that most readers in
this newsgroup do not know what algebraic numbers are.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jun 27 '06 #19
In article <J1********@cwi.nl>, Dik T. Winter <Di********@cwi.nl> wrote:
> Infinitely many bits doesn't give you "100% accuracy". You will
> only be able to represent the algebraic numbers.
No, that would be true for finite but arbitrarily long bit strings.
And that is also false. Finite but arbitrarily long bit strings give
you only a subset of the rational numbers.


Sorry, I didn't say what I meant. I *meant* to say that with finite
but unlimited strings of bits you can represent a countable set such
as the algebraic numbers, but if infinitely long strings are allowed
you can represent uncountable sets such as the reals. Obviously to
represent the algebraic numbers you would not be using a plain
positional notation.

-- Richard
Jun 27 '06 #20
Jordi wrote:
Thanks for your reply!

Please don't top-post. Your replies belong following or interspersed
with properly trimmed quotes. See the other 99% of the posts in this
group or <http://www.caliburn.nl/topposting.html (thanks Keith).


Brian
Jun 27 '06 #21
Richard Tobin wrote:
In article <J1********@cwi.nl>, Dik T. Winter <Di********@cwi.nl> wrote:
> Infinitely many bits doesn't give you "100% accuracy". You will
> only be able to represent the algebraic numbers. No, that would be true for finite but arbitrarily long bit strings.

And that is also false. Finite but arbitrarily long bit strings give
you only a subset of the rational numbers.


Sorry, I didn't say what I meant. I *meant* to say that with finite
but unlimited strings of bits you can represent a countable set such
as the algebraic numbers, but if infinitely long strings are allowed
you can represent uncountable sets such as the reals. Obviously to
represent the algebraic numbers you would not be using a plain
positional notation.


Actually, this is wrong.

The set of integers and the set of rationals are both countable as shown
in http://web01.shu.edu/projects/reals/.../countble.html
The set of reals in not countable, as shown in
http://web01.shu.edu/projects/reals/.../uncntble.html

In fact, it is provable that the set of reals between 0 and 1 is larger
than the set of all integers. However, amusingly enough, the set of
reals between 0 and 1 is the same size as the set of all reals.

I attended a one hour lecture on infinity, and it was probably the most
amusing maths lecture I ever attended because is showed how completely
absurd maths can be whilst also being completely consistent and useful.

Whilst interesting, this is not really topical here. Have a look at
http://web01.shu.edu/projects/reals/index.html or any of the many other
sites that cover this.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jun 27 '06 #22

"Jordi" <jb*****@gmail.com> wrote in message
news:11*********************@i40g2000cwc.googlegro ups.com...
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
.0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

It does this type of thing because:-

1. It represents numbers not as decimal fractions but as binary fractions.
2. It only has a finit number of digits/bits

The effect is some what similar to the following:-

assume we are working in decimal to three digits. We have 1.0/3.0 = 0.33.
Multiply up again and 3*0.33=0.99.
Any help or tips are greatly appreciated!


Depends on what you are doing. If you can try and scale the problem so you
can work in integers.E.G. if its dollars and cents work in cents.
As others have said use "double" rather than float can help. Might help to
help the compiler. Saying things like "var/5.0" or even "var*0.5" (but watch
out because although "0.5" usually converts to an exact binary fraction,
"0.l" doesn't...) You might also need to learn how to use the constants in
<float.h> and <math.h> The "The Standard C Library" by Plauger has some
usefull stuff on these. The trouble is when you start using floating point
you may need to start to understand the both the maths behind the
calculations, and what really happens in the FP routines.
Its just too easy to subtract two similar sized numbers end up with residual
error as an answer....

Jun 27 '06 #23

"Gordon Burditt" <go***********@burditt.org> wrote in message
news:12*************@corp.supernews.com...
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002
There is no exact representation of most decimal numbers in binary
floating point. Float only claims to have 6 digits, and your output
is off by 2 counts in the 8th digit. You have little cause to complain
that you didn't get the accuracy advertised.

45.4 as float:
Before:

45.39999771118164062500000000000000000000000000000 0000000000000 Value: 45.40000152587890625000000000000000000000000000000 0000000000000 After: 45.40000534057617187500000000000000000000000000000 0000000000000
The three choices are shown above. The value you got was the closest
possible representation of the mathematically correct answer in an
IEEE 32-bit floating point number.
Obviously, the output should be 45.4 (or 45.400000), but for some
There is no such number exactly representable in binary floating point.
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.


Then use a more precise floating-point value, like double or long double.
(That's just putting off the problem, though).

* It seems that it is not .000002 is added, but rather
.0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?


Use floating-point hardware with an infinite number of bits. Or,
if that's too expensive, just use MORE bits.


Or switch to a language that uses decimal numbers, such as REXX, However
even REXX only allows a finite number of digits so you can still get into
problems....

Gordon L. Burditt

Jun 27 '06 #24
On 26 Jun 2006 17:21:39 -0700, in comp.lang.c , "Jordi"
<jb*****@gmail.com> wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002


This is a FAQ. Please read it, and then read Goldberg.

Hint: its nothing to do with C, its entirely to do with how computers
store floating point numbers.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jun 27 '06 #25
On Tue, 27 Jun 2006 09:36:48 -0400, Peter Boettcher <bo*******@ll.mit.edu> wrote:
See "What Every Computer Scientist Should Know About Floating-Point
Arithmetic" by David Goldberg:

http://www.weblearn.hs-bremen.de/ris...s/goldberg.pdf


Or the updated version:

ftp://ftp.quitt.net/outgoing/goldbergFollowup.pdf

--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
Jun 27 '06 #26
In article <rb************@news.flash-gordon.me.uk> Flash Gordon <sp**@flash-gordon.me.uk> writes:
Richard Tobin wrote:
In article <J1********@cwi.nl>, Dik T. Winter <Di********@cwi.nl> wrote:
>> Infinitely many bits doesn't give you "100% accuracy". You will
>> only be able to represent the algebraic numbers.
No, that would be true for finite but arbitrarily long bit strings.

And that is also false. Finite but arbitrarily long bit strings give
you only a subset of the rational numbers.


Sorry, I didn't say what I meant. I *meant* to say that with finite
but unlimited strings of bits you can represent a countable set such
as the algebraic numbers, but if infinitely long strings are allowed
you can represent uncountable sets such as the reals. Obviously to
represent the algebraic numbers you would not be using a plain
positional notation.


Actually, this is wrong.


It is wrong, but not for the reason you mention. Indeed with finite strings
(when we consider them as binary representations) you can represent countable
sets, but *not* the algebraic numbers (although they are countable). Only a
subset of the rationals. With (countably) infinite long strings you can
represent all reals.
The set of integers and the set of rationals are both countable as shown
in http://web01.shu.edu/projects/reals/.../countble.html
The set of reals in not countable, as shown in
http://web01.shu.edu/projects/reals/.../uncntble.html
Indeed. But the set of algebraic numbers is also countable, as is the set
of computable numbers (the latter is the largest countable set of numbers
in some sense). I may note that the set of algebraic numbers is a proper
subset of the set of reals.
In fact, it is provable that the set of reals between 0 and 1 is larger
than the set of all integers. However, amusingly enough, the set of
reals between 0 and 1 is the same size as the set of all reals.


And the set of even integers is the same size as the set of all integers.
And the set of integers of the form 2 ** n is the same size as the set of
all integers.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jun 27 '06 #27
In article <rb************@news.flash-gordon.me.uk>,
Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Sorry, I didn't say what I meant. I *meant* to say that with finite
but unlimited strings of bits you can represent a countable set such
as the algebraic numbers, but if infinitely long strings are allowed
you can represent uncountable sets such as the reals. Obviously to
represent the algebraic numbers you would not be using a plain
positional notation.
Actually, this is wrong. The set of integers and the set of rationals are both countable as shown
in http://web01.shu.edu/projects/reals/.../countble.html
The set of reals in not countable, as shown in
http://web01.shu.edu/projects/reals/.../uncntble.html


This is true, but I am at a loss as to what you think it contradicts
what I said.

-- Richard
Jun 28 '06 #28
In article <J1********@cwi.nl>, Dik T. Winter <Di********@cwi.nl> wrote:
Sorry, I didn't say what I meant. I *meant* to say that with finite
but unlimited strings of bits you can represent a countable set such
as the algebraic numbers, but if infinitely long strings are allowed
you can represent uncountable sets such as the reals. Obviously to
represent the algebraic numbers you would not be using a plain
positional notation.
It is wrong, but not for the reason you mention. Indeed with finite strings
(when we consider them as binary representations) you can represent countable
sets, but *not* the algebraic numbers (although they are countable).


That's why I said "not using a plain positional notation". You can
represent the algebraic numbers, and all computable numbers, using
finite sequences of bits.

For example, you could represent each algebraic number as a list of
the integer coefficients of a polynomial it satifisfies, along with an
integer indicating which root it is. You could then encode the
sequence of integers as a sequence of bits in whatever manner you
prefer. Of course, the arithmetic operations are non-trivial given
this representation.

-- Richard
Jun 28 '06 #29
Richard Tobin wrote:
In article <rb************@news.flash-gordon.me.uk>,
Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Sorry, I didn't say what I meant. I *meant* to say that with finite
but unlimited strings of bits you can represent a countable set such
as the algebraic numbers, but if infinitely long strings are allowed
you can represent uncountable sets such as the reals. Obviously to
represent the algebraic numbers you would not be using a plain
positional notation.

Actually, this is wrong.

The set of integers and the set of rationals are both countable as shown
in http://web01.shu.edu/projects/reals/.../countble.html
The set of reals in not countable, as shown in
http://web01.shu.edu/projects/reals/.../uncntble.html


This is true, but I am at a loss as to what you think it contradicts
what I said.


It was a brain fart. I have now recalibrated my brain. Sorry.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jun 28 '06 #30
ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
In article <J1********@cwi.nl>, Dik T. Winter <Di********@cwi.nl> wrote:
> > Sorry, I didn't say what I meant. I *meant* to say that with finite
> > but unlimited strings of bits you can represent a countable set such
> > as the algebraic numbers, but if infinitely long strings are allowed
> > you can represent uncountable sets such as the reals. Obviously to
> > represent the algebraic numbers you would not be using a plain
> > positional notation.

It is wrong, but not for the reason you mention. Indeed with finite strings
(when we consider them as binary representations) you can represent countable
sets, but *not* the algebraic numbers (although they are countable).


That's why I said "not using a plain positional notation". You can
represent the algebraic numbers, and all computable numbers, using
finite sequences of bits.

For example, you could represent each algebraic number as a list of
the integer coefficients of a polynomial it satifisfies, along with an
integer indicating which root it is. You could then encode the
sequence of integers as a sequence of bits in whatever manner you
prefer. Of course, the arithmetic operations are non-trivial given
this representation.


You can even represent a number by a character string specifying, in
unambiguous English, the computation of the number.

For example:

"e"
"the square root of pi"
"the smallest number not specifiable by a 60-character string"

(oops)

--
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.
Jun 28 '06 #31
Ian Collins wrote:
Jordi wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
..0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?
It doesn't, the floating point hardware or emulation does.

Floating point isn't precise. Avoid floats and use doubles, even then,
you have to understand the limitations of floating point math.

Floating point is precise. It is not exact. C's float typically has 24
bits of precision and the value of a float can be precise to 1 in 16
million or so. The mantissa of the double is 53 bits and provides an
exquisitely precise (if not exact) value on the order of 9e15.
You must have a dodgy FPU, the result is 45.400000 on my system :)

There are no 'dodgy' FPU's among our audience.

I hope this doesn't wrap or that otherwise you can figure it out ..

01000010 00110101 10011001 10011010
Exp = 132 (6)
00000110
Man = .10110101 10011001 10011010
4.54000015e+01

This (above) is the result of 'float f = 227.0 / 5;'
The last line is the result of 'printf("%.8e", f);'

01000000 01000110 10110011 00110011 00110011 00110011 00110011 00110011
Exp = 1028 (6)
000 00000110
Man = .10110 10110011 00110011 00110011 00110011 00110011 00110011
4.5399999999999999e+01

This (above) is the result of 'double d = 227.0 / 5;'
The last line is the result of 'printf("%.16e", d);'
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jun 29 '06 #32
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
"the smallest number not specifiable by a 60-character string"

(oops)


Sorry, that would be defined to invoke undefined behaviour, and is
therefore off-topic.

-- Richard
Jun 29 '06 #33
Jordi wrote:
I said I wouldn't try doubles in the real project, but it didn't prove
that difficult and I couldn't let it rest. Anyway, it didn't work as
well as I hoped. This is some of the output I got:
x = 64.200000 / (107.000000 / 5) = 64.200000 / 21.400000 = 3.000000 = 2

Notice the 3.000000 = 2? That's what's screwing my program over.

Anyway, as I understand from you guys, I need infinite bits to get 100%
accuracy. That's probably not going to happen anytime soon, so I need
another solution. Is there a way to make the program use the calculated
3.000000 instead of the 2.9999999999999999999999999 it actually
calculated? Is there some way to specify how accurate I need things?

Thanks for any help!

Ian Collins wrote:
Jordi wrote:
I have made a little C program that generates the following output:
227.000000 / 5 = 45.400002

Here's the code:
int main (int argc, char* argv[]) {
float var = 227;
printf("%f / 5 = %f\n", var, var / 5);
return 0;
}

Obviously, the output should be 45.4 (or 45.400000), but for some
mysterious reason C decided to add 0.000002* to the result. The error
might seem minor and this program is obviously trivial, but I need to
do similar calculations in a much bigger project and the problem I'm
encountering is caused by exactly this error.

* It seems that it is not .000002 is added, but rather
..0000015258789076710855... (which I found out after subtracting 45.4
from the result and then multiplying it with 10,000,000,000,000,000)

Why does C do this and what can I do about it?

It doesn't, the floating point hardware or emulation does.

Floating point isn't precise. Avoid floats and use doubles, even then,
you have to understand the limitations of floating point math.

You must have a dodgy FPU, the result is 45.400000 on my system :)

--
Ian Collins.

We all need to appreciate that our computer works in binary, not
decimal. The result that you see from printf is a conversion from binary
floating point to decimal. The conversion is as good as anybody can do
but we have to know that while simple integrals (up to a point) can be
exactly represented in a binary floating point object, but as soon as we
get to the right of the radix point, it falls apart.

But, the floating point is the better number. If you don't get what you
like from printf, adjust the format parameters.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jun 29 '06 #34
In article <w8******************************@comcast.com>,
Joe Wright <jo********@comcast.net> wrote:
Ian Collins wrote:
You must have a dodgy FPU, the result is 45.400000 on my system :)

There are no 'dodgy' FPU's among our audience.


Pentium FDIV bug.

http://en.wikipedia.org/wiki/Pentium_FDIV_bug
--
Prototypes are supertypes of their clones. -- maplesoft
Jun 29 '06 #35
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote

In fact, it is provable that the set of reals between 0 and 1 is larger
than the set of all integers.

Almost trival in fact.

int main(void)
{
if(sizeof(double) > sizeof(long))
printf("More reals\n");
else
printf("More integers\n");

return 0;
}
--
Buy my book 12 Common Atheist Arguments (refuted)
$1.25 download or $7.20 paper, available www.lulu.com/bgy1mm
Jun 30 '06 #36
"Malcolm" <re*******@btinternet.com> writes:
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote
In fact, it is provable that the set of reals between 0 and 1 is larger
than the set of all integers.

Almost trival in fact.

int main(void)
{
if(sizeof(double) > sizeof(long))
printf("More reals\n");
else
printf("More integers\n");

return 0;
}


If this were at all relevant to the original statement, I'd say
something about padding bits.

--
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.
Jun 30 '06 #37
Malcolm wrote:
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote
In fact, it is provable that the set of reals between 0 and 1 is larger
than the set of all integers.

Almost trival in fact.

int main(void)
{
if(sizeof(double) > sizeof(long))
printf("More reals\n");
else
printf("More integers\n");

return 0;
}


That obviously does not prove the statement. sizeof(double) does not
tell you how many reals there are between 0 and 1.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jun 30 '06 #38
inmatarian wrote:
Eww, top posting.

use used and (int) cast. At any rate, this isn't C's fault, it's the
fault of IEEE's float specification, that says that you only need 32
bits of precision, instead of infinity.
You must have a better set of memory chips than anyone else has.
Please post pictures of your memory box that holds these infinite
precision floating pointy numbers. Also, since you obviously have
the precision necessary, please tell us what the last three digits
of PI and e are. Always wondered if PI was a palindrome, or e with
the digits reversed.

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jul 3 '06 #39

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

Similar topics

49
by: Relaxin | last post by:
It is just me or has MS created some of the worst ways to access and display data? You can use a DataSet, but if you want to sort or filter the data to must use a DataView which is created from...
761
by: Neo-LISPer | last post by:
Hey Recently, I researched using C++ for game programming and here is what I found: C++ game developers spend a lot of their time debugging corrupted memory. Few, if any, compilers offer...
4
by: Sehri | last post by:
Hi all, I have just started developing a math companion tool with VS2005 and I just ran into a problem when trying to add the description of a formula. Doed anyone know how can I add math...
2
by: Nicolas | last post by:
Why does for the same code I got different result the VB code gave me what I want why not the csharp? Thank you for your help... CSHARP CODE int sx, sy; double sdegrees; sdegrees = (90 -...
11
by: Sambo | last post by:
I have the following module: ------------------------------- import math def ac_add_a_ph( amp1, ph1, amp2, ph2 ): amp3 = 0.0 ph3 = 0.0 ac1 = ( 0, 0j ) ac2 = ( 0, 0j )
4
by: =?Utf-8?B?UmVuZQ==?= | last post by:
Hello everyone I have a problem with Math.Round, it´s ocurring some strange: Math.Round(12.985) = 12.98, it´s wrong. It should be: 12.99 Why?? What is the problem? Help ME !!!!
9
by: DaiOz | last post by:
Hi guys im doing a course which includes some JavaScript and I need help with the following question please, The code I have so far is below but I don't think its right please help as I need...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
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)...
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
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.