446,419 Members | 1,123 Online
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,419 IT Pros & Developers. It's quick & easy.

# C sucks at math? (help)

 P: n/a 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 Replies

 P: n/a 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

 P: n/a In article <11*********************@i40g2000cwc.googlegroups. com>, 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;} 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

 P: n/a 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

 P: n/a 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" 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

 P: n/a >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 errormight seem minor and this program is obviously trivial, but I need todo similar calculations in a much bigger project and the problem I'mencountering 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.4from 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

 P: n/a 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

 P: n/a "Jordi" 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 . You've asked question 14.1. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 27 '06 #8

 P: n/a >I said I wouldn't try doubles in the real project, but it didn't provethat difficult and I couldn't let it rest. Anyway, it didn't work aswell as I hoped. This is some of the output I got:x = 64.200000 / (107.000000 / 5) = 64.200000 / 21.400000 = 3.000000 = 2Notice 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 needanother solution. Is there a way to make the program use the calculated3.000000 instead of the 2.9999999999999999999999999 it actuallycalculated? 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

 P: n/a 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

 P: n/a In article <11*********************@m73g2000cwd.googlegroups. com>, Jordi wrote:I said I wouldn't try doubles in the real project, but it didn't provethat difficult and I couldn't let it rest. Anyway, it didn't work aswell 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 needanother solution. Is there a way to make the program use the calculated3.000000 instead of the 2.9999999999999999999999999 it actuallycalculated? 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

 P: n/a 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

 P: n/a 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

 P: n/a "Bill Pursell" 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 San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 27 '06 #14

 P: n/a In article <11**********************@i40g2000cwc.googlegroups .com> "Bill Pursell" 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

 P: n/a In article Keith Thompson writes: "Bill Pursell" 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

 P: n/a In article , Keith Thompson wrote: "Bill Pursell" 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 implementationshould provide at least aleph-one bits. Doesn't that have bit-order problems? -- Richard Jun 27 '06 #17

 P: n/a "Jordi" 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

 P: n/a In article ri*****@cogsci.ed.ac.uk (Richard Tobin) writes: In article , Keith Thompson wrote:"Bill Pursell" 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

 P: n/a In article , Dik T. Winter 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 giveyou 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

 P: n/a 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

 P: n/a Richard Tobin wrote: In article , Dik T. Winter 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

 P: n/a "Jordi" 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 and 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

 P: n/a "Gordon Burditt" 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 errormight seem minor and this program is obviously trivial, but I need todo similar calculations in a much bigger project and the problem I'mencountering 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.4from 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

 P: n/a On 26 Jun 2006 17:21:39 -0700, in comp.lang.c , "Jordi" 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

 P: n/a On Tue, 27 Jun 2006 09:36:48 -0400, Peter Boettcher wrote:See "What Every Computer Scientist Should Know About Floating-PointArithmetic" 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 _ Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up Jun 27 '06 #26

 P: n/a In article Flash Gordon writes: Richard Tobin wrote: In article , Dik T. Winter 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

 P: n/a In article , Flash Gordon 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 shownin http://web01.shu.edu/projects/reals/.../countble.htmlThe set of reals in not countable, as shown inhttp://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

 P: n/a In article , Dik T. Winter 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 countablesets, 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

 P: n/a Richard Tobin wrote: In article , Flash Gordon 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

 P: n/a ri*****@cogsci.ed.ac.uk (Richard Tobin) writes: In article , Dik T. Winter 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 countablesets, 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 San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 28 '06 #31

 P: n/a 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

 P: n/a In article , Keith Thompson 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

 P: n/a 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

 P: n/a In article , Joe Wright 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

 P: n/a "Flash Gordon" 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

 P: n/a "Malcolm" writes: "Flash Gordon" 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 San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 30 '06 #37

 P: n/a Malcolm wrote: "Flash Gordon" 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

 P: n/a 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 discussion thread is closed

Replies have been disabled for this discussion.