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

# Deviation of double

 P: n/a Hallo NG My problem is the deviation of the floating point datatypes. 90.625 is not exactly 90.625. It is 90.624999999.... on my system. Now I tried to find a solution for my problem but I couldn't think of one. So I tried to write a work-arround which should solve the problem for the most numbers. What do you think of this: (I know it is not a perfect solution....) double dValue = ...; if (dValue >= 10000000000000LL) { nInValue += 0.01; } else if (dValue >= 1000000000000LL) { nInValue += 0.001; } else if (dValue >= 100000000000LL) { nInValue += 0.0001; } else if (dValue >= 10000000000LL) { nInValue += 0.00001; } else if (dValue >= 1000000000) { nInValue += 0.000001; } else if (dValue >= 100000000) { nInValue += 0.0000001; } else if (dValue >= 10000000) { nInValue += 0.00000001; } else if (dValue >= 1000000) { nInValue += 0.000000001; } else if (dValue >= 100000) { nInValue += 0.0000000001; } else if (dValue >= 10000) { nInValue += 0.00000000001; } else if (dValue >= 1000) { nInValue += 0.000000000001; } else if (dValue >= 100) { nInValue += 0.0000000000001; } else if (dValue >= 10) { nInValue += 0.00000000000001; } else if (dValue < 0) { nInValue -= 0.000000000000001; } // if Greets Chris Jul 22 '05 #1
16 Replies

 P: n/a "Christian Meier" wrote in message news:c8**********@newshispeed.ch... Hallo NG My problem is the deviation of the floating point datatypes. 90.625 is not exactly 90.625. It is 90.624999999.... on my system. Now I tried to find a solution for my problem but I couldn't think of one. So I tried to write a work-arround which should solve the problem for the most numbers. What do you think of this: (I know it is not a perfect solution....) double dValue = ...; if (dValue >= 10000000000000LL) { nInValue += 0.01; } else if (dValue >= 1000000000000LL) { nInValue += 0.001; } else if (dValue >= 100000000000LL) { nInValue += 0.0001; } else if (dValue >= 10000000000LL) { nInValue += 0.00001; } else if (dValue >= 1000000000) { nInValue += 0.000001; } else if (dValue >= 100000000) { nInValue += 0.0000001; } else if (dValue >= 10000000) { nInValue += 0.00000001; } else if (dValue >= 1000000) { nInValue += 0.000000001; } else if (dValue >= 100000) { nInValue += 0.0000000001; } else if (dValue >= 10000) { nInValue += 0.00000000001; } else if (dValue >= 1000) { nInValue += 0.000000000001; } else if (dValue >= 100) { nInValue += 0.0000000000001; } else if (dValue >= 10) { nInValue += 0.00000000000001; } else if (dValue < 0) { nInValue -= 0.000000000000001; } // if I'm not sure what you are trying to achieve by doing this, and what about negative numbers? The problem is that many numbers cannot be exactly represented in floating point format, just like 1/3 cannot be exactly represented with just decimal numbers. Fiddling with floating point values will only help in very specific cases at best. If the inevitable rounding errors of floating point numbers is not acceptable for your application, maybe a fixed point format is more appropriate for your application. -- Peter van Merkerk peter.van.merkerk(at)dse.nl Jul 22 '05 #2

 P: n/a Christian Meier wrote: Hallo NG My problem is the deviation of the floating point datatypes. 90.625 is not exactly 90.625. It is 90.624999999.... on my system. Now I tried to find a solution for my problem but I couldn't think of one. Forgive me. What was your problem? So I tried to write a work-arround which should solve the problem for the most numbers. What do you think of this: (I know it is not a perfect solution....) I doesn't look like solution to anything. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #3

 P: n/a "Christian Meier" wrote in news:c8**********@newshispeed.ch: Hallo NG My problem is the deviation of the floating point datatypes. 90.625 is not exactly 90.625. It is 90.624999999.... on my system. Now I tried to find a solution for my problem but I couldn't think of one. So I tried to write a work-arround which should solve the problem for the most numbers. What do you think of this: (I know it is not a perfect solution....) (...) You can't "work around" the floating point precision limitation. You can only use more bits to have a better approximation. An exact representation would require an infinite amount of bits, wouldn't it? That's how computers work, sorry. You can use a specialised extended-precision arithmetics library, though, like the GNU MP http://www.swox.com/gmp/ for example. -- :: bartekd [at] o2 [dot] pl Jul 22 '05 #4

 P: n/a bartek wrote: [...] You can't "work around" the floating point precision limitation. Yes, he can (and often should). He could use fractions. 90.625 is 725/8. If all arithmetic operations are done in fractions, it's possible to achieve exact solution (using large enough integers to represent the numbers). BTW, to the OP: I have a hard time believing that 90 5/8 is not represented precisely on your machine. It's quite possible that you _expect_ it to be represented precisely, like after multiplying 0.90625 with 100, but you don't have your 0.90625 precisely to begin with. That's the problem, I believe. V Jul 22 '05 #5

 P: n/a "Karl Heinz Buchegger" schrieb im Newsbeitrag news:40***************@gascad.at... Christian Meier wrote: Hallo NG My problem is the deviation of the floating point datatypes. 90.625 is not exactly 90.625. It is 90.624999999.... on my system. Now I tried to find a solution for my problem but I couldn't think of one. Forgive me. What was your problem? So I tried to write a work-arround which should solve the problem for the most numbers. What do you think of this: (I know it is not a perfect solution....) I doesn't look like solution to anything. -- Karl Heinz Buchegger kb******@gascad.at Sorry, wasn't a really good description of my problem. I will give more infos: I have a function with two parameters. One of type double, the other one is an int. string func (double dValue, int iDigits); This function must return a string which represents the double value. iDigits is the number of digits after the point. For this I use sprintf. And now I got a problem. When passing 90.625 to the function (iDigits = 2) then the function returned 90.62 instead of 90.63. I found out that the double is stored as 90.624999999... on my system. So I need a solution for this. The function has to return 90.63. So I thought I can add a small value to dValue before rounding. And the double has a limit of 15 decimal digits on my system. So I tried to write a work-arround as described in my first post. Can you now understand my problem? Regards, Chris Jul 22 '05 #6

 P: n/a Victor Bazarov wrote: bartek wrote: [...] You can't "work around" the floating point precision limitation. Yes, he can (and often should). He could use fractions. 90.625 is 725/8. If all arithmetic operations are done in fractions, it's possible to achieve exact solution (using large enough integers to represent the numbers). Hmm. I wonder how you would represent PI in such a system :-) -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #7

 P: n/a "Victor Bazarov" schrieb im Newsbeitrag news:Cu****************@dfw-read.news.verio.net... bartek wrote: [...] You can't "work around" the floating point precision limitation. Yes, he can (and often should). He could use fractions. 90.625 is 725/8. If all arithmetic operations are done in fractions, it's possible to achieve exact solution (using large enough integers to represent the numbers). BTW, to the OP: I have a hard time believing that 90 5/8 is not represented precisely on your machine. It's quite possible that you _expect_ it to be represented precisely, like after multiplying 0.90625 with 100, but you don't have your 0.90625 precisely to begin with. That's the problem, I believe. V It does..... these lines: double d = 90.625; char c[10]; sprintf(c, "%.2f", h); std::cout << c << std::endl; return the following output: 90.62 Greetings Chris Jul 22 '05 #8

 P: n/a Karl Heinz Buchegger wrote: Victor Bazarov wrote:bartek wrote:[...]You can't "work around" the floating point precision limitation.Yes, he can (and often should). He could use fractions. 90.625 is 725/8. If all arithmetic operations are done in fractions, it's possible toachieve exact solution (using large enough integers to represent the numbers). Hmm. I wonder how you would represent PI in such a system :-) 22/7 of course (Gods know a better value). On a serious note, however, I suspect that the OP starts with integral values. If that's so, then the result should be representable as a fractional value, if all operations are arithmetic. V Jul 22 '05 #9

 P: n/a Christian Meier wrote: "Victor Bazarov" schrieb im Newsbeitrag news:Cu****************@dfw-read.news.verio.net...bartek wrote:[...]You can't "work around" the floating point precision limitation.Yes, he can (and often should). He could use fractions. 90.625 is 725/8. If all arithmetic operations are done in fractions, it's possible toachieve exact solution (using large enough integers to represent the numbers).BTW, to the OP: I have a hard time believing that 90 5/8 is notrepresented precisely on your machine. It's quite possible that you_expect_ it to be represented precisely, like after multiplying 0.90625with 100, but you don't have your 0.90625 precisely to begin with. That'sthe problem, I believe.V It does..... these lines: double d = 90.625; char c[10]; sprintf(c, "%.2f", h); std::cout << c << std::endl; return the following output: 90.62 They do????? Declare/define/initialise 'd', then print 'h' and expect something sensible? Come on... I took your code, fixed it, put it in a write surrounding and got 90.63. Try again, this time the right version: #include #include using namespace std; int main() { double d = 90.625; char c[10]; sprintf(c, "%.2f", d); cout << c << endl; return 0; } V Jul 22 '05 #10

 P: n/a Christian Meier wrote: Sorry, wasn't a really good description of my problem. I will give more infos: I have a function with two parameters. One of type double, the other one is an int. string func (double dValue, int iDigits); This function must return a string which represents the double value. iDigits is the number of digits after the point. For this I use sprintf. And now I got a problem. When passing 90.625 to the function (iDigits = 2) then the function returned 90.62 instead of 90.63. I found out that the double is stored as 90.624999999... on my system. So I need a solution for this. The function has to return 90.63. So I thought I can add a small value to dValue before rounding. And the double has a limit of 15 decimal digits on my system. So I tried to write a work-arround as described in my first post. Can you now understand my problem? I see. Hmm. There is indeed not much you can do other then adding some small constant depending on the number of digits you want after comma. But note: This doesn't solve your problem, it just hides it for that number. There will always be some border where one or the other digit shows up. If your numbers are close to that border you will see exactly that problem. In your case that border is the digit 5. By adding some small constant you simply shift that border a little bit higher or lower, but the border is still there. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #12

 P: n/a "Victor Bazarov" schrieb im Newsbeitrag news:22****************@dfw-read.news.verio.net... Christian Meier wrote: "Victor Bazarov" schrieb im Newsbeitrag news:Cu****************@dfw-read.news.verio.net...bartek wrote:[...]You can't "work around" the floating point precision limitation.Yes, he can (and often should). He could use fractions. 90.625 is 725/8. If all arithmetic operations are done in fractions, it's possible toachieve exact solution (using large enough integers to represent the numbers).BTW, to the OP: I have a hard time believing that 90 5/8 is notrepresented precisely on your machine. It's quite possible that you_expect_ it to be represented precisely, like after multiplying 0.90625with 100, but you don't have your 0.90625 precisely to begin with. That'sthe problem, I believe.V It does..... these lines: double d = 90.625; char c[10]; sprintf(c, "%.2f", h); std::cout << c << std::endl; return the following output: 90.62 They do????? Declare/define/initialise 'd', then print 'h' and expect something sensible? Come on... I took your code, fixed it, put it in a write surrounding and got 90.63. Try again, this time the right version: #include #include using namespace std; int main() { double d = 90.625; char c[10]; sprintf(c, "%.2f", d); cout << c << endl; return 0; } V Believe me!!! Ok, I'll prove it.... The following is my bash output: ~/> cat main.cpp #include #include using namespace std; int main() { double d = 90.625; char c[10]; sprintf(c, "%.2f", d); cout << c << endl; return 0; } ~/> g++ -o prog main.cpp ~/> prog 90.62 Do you need more infos that you can believe me? Greets Chris Jul 22 '05 #13