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

# Weirdness: (-0.666667 + 0.333333)

 P: n/a Hi, I'm experiencing some weirdness in a program, when subtracting 2 (double)'s which should result in 0, but instead it returns -1.11022e-16. It looks to me that changing the double x_step decleration to unsigned type, might help, but the compiler complains when i try that. Any ideas ? #include using namespace std; int main(int argc, char *argv[]) { double x1 = -1; double x2 = 1; double nx = 6; int pos = 0; double x = 0.0; double x_step = 0.0; x_step = (x2 - x1) / nx; x = x1; for (pos = 0; pos < nx; pos++) { cout << x << " +\t" << x_step << " =\t " << (x + x_step) << endl; x = x + x_step; } return 0; } Output: -1 + 0.333333 = -0.666667 -0.666667 + 0.333333 = -0.333333 -0.333333 + 0.333333 = -1.11022e-16 -1.11022e-16 + 0.333333 = 0.333333 0.333333 + 0.333333 = 0.666667 0.666667 + 0.333333 = 1 Jul 22 '05 #1
15 Replies

 P: n/a Corne' Cornelius wrote in news:P6********************@is.co.za: Hi, I'm experiencing some weirdness in a program, when subtracting 2 (double)'s which should result in 0, but instead it returns -1.11022e-16. It looks to me that changing the double x_step decleration to unsigned type, might help, but the compiler complains when i try that. Any ideas ? That's the nature of floating point arithmetic. You shouldn't compare against exact values, beacause of rounding errors (which are unavoidable, though usually very small). You should check against some small epsilon range instead of comparing exact numbers. -- :: bartekd [at] o2 [dot] pl Jul 22 '05 #2

 P: n/a I've rounded the x_step var to a couple of places after the decimal point which seem to help, i need a number closer to 0 then what the overflow results in. Thanks ! bartek wrote: Corne' Cornelius wrote in news:P6********************@is.co.za:Hi,I'm experiencing some weirdness in a program, when subtracting 2(double)'s which should result in 0, but instead it returns-1.11022e-16. It looks to me that changing the double x_step declerationto unsigned type, might help, but the compiler complains when i try that.Any ideas ? That's the nature of floating point arithmetic. You shouldn't compare against exact values, beacause of rounding errors (which are unavoidable, though usually very small). You should check against some small epsilon range instead of comparing exact numbers. Jul 22 '05 #3

 P: n/a Hi! Corne' Cornelius writes: I'm experiencing some weirdness in a program, when subtracting 2(double)'s which should result in 0, but instead it returns-1.11022e-16. It looks to me that changing the double x_step declerationto unsigned type, might help, but the compiler complains when i try that. The problem is that real numbers on a computer have limited accuracy. Results of substracting two real numbers that are (almost) equal, should not be trusted. Solutions to this problem generally depend on what exactly you want to do. Bye, Chris Dams Jul 22 '05 #4

 P: n/a Corne' Cornelius wrote: I'm experiencing some weirdness in a program, when subtracting 2 (double)'s which should result in 0, but instead it returns -1.11022e-16. Doubles do not always exactly represent the value of a number but are an approximation of the value. This is especially true for computed values. See http://docs.sun.com/source/806-3568/ncg_goldberg.html Jul 22 '05 #5

 P: n/a Corne' Cornelius wrote in news:-b********************@is.co.za: I've rounded the x_step var to a couple of places after the decimal point which seem to help, i need a number closer to 0 then what the overflow results in. first... #include ....then... std::numeric_limits::epsilon() ....will give you the smallest possible increment from 1. Unfortunately rounding errors can be bigger than that. It all depends on what you're actually doing. You should choose the threshold based on that. -- :: bartekd [at] o2 [dot] pl Jul 22 '05 #6

 P: n/a bartek wrote in news:Xn**********************************@153.19.2 51.200: Corne' Cornelius wrote in news:-b********************@is.co.za: I've rounded the x_step var to a couple of places after the decimal point which seem to help, i need a number closer to 0 then what the overflow results in. first... #include ...then... std::numeric_limits::epsilon() ...will give you the smallest possible increment from 1. Unfortunately rounding errors can be bigger than that. It all depends on what you're actually doing. You should choose the threshold based on that. I mean -- based on what you're doing, not on numeric_limits::epsilon() that is. -- :: bartekd [at] o2 [dot] pl Jul 22 '05 #7

 P: n/a Bill Seurer wrote: Doubles do not always exactly represent the value of a number but are an approximation of the value. This is especially true for computed values. Doubles exactly represent the value that they hold. They sometimes don't hold the result that you would get from some computation with infinite precision arithemetic. But, then, neither do ints. In their first week future programmers learn to accept that (1/3)*3 isn't 1. For some reason it's harder for them to accept that with floating point values. -- Pete Becker Dinkumware, Ltd. (http://www.dinkumware.com) Jul 22 '05 #8

 P: n/a Corne' Cornelius wrote: Hi, I'm experiencing some weirdness in a program, when subtracting 2 (double)'s which should result in 0, but instead it returns -1.11022e-16. It looks to me that changing the double x_step decleration to unsigned type, might help, but the compiler complains when i try that. Any ideas ? Don't compare two floating point numbers as such. Use the trick of an epsilon interval by Knuth (implemented in the fcmp package available at sourceforge.net) described in TAOCP Vol 2 Seminumerical algorithms. bye, gert Jul 22 '05 #9

 P: n/a i should've made it more clear what i actually want to do. I'm not really trying to compare 2 double which could be in accurate becuase of rounding errors. I'm writing a program that draws graphs on a cartesian plane, so in order to go on the x-axis from say -2, to +2, in 20 intervals, i need one of these point to be zero or very close to it. how could i make sure i don't get rounding problems ? Corne' Cornelius wrote: Hi, I'm experiencing some weirdness in a program, when subtracting 2 (double)'s which should result in 0, but instead it returns -1.11022e-16. It looks to me that changing the double x_step decleration to unsigned type, might help, but the compiler complains when i try that. Any ideas ? #include using namespace std; int main(int argc, char *argv[]) { double x1 = -1; double x2 = 1; double nx = 6; int pos = 0; double x = 0.0; double x_step = 0.0; x_step = (x2 - x1) / nx; x = x1; for (pos = 0; pos < nx; pos++) { cout << x << " +\t" << x_step << " =\t " << (x + x_step) << endl; x = x + x_step; } return 0; } Output: -1 + 0.333333 = -0.666667 -0.666667 + 0.333333 = -0.333333 -0.333333 + 0.333333 = -1.11022e-16 -1.11022e-16 + 0.333333 = 0.333333 0.333333 + 0.333333 = 0.666667 0.666667 + 0.333333 = 1 Jul 22 '05 #10

 P: n/a Corne' Cornelius wrote: i should've made it more clear what i actually want to do. I'm not really trying to compare 2 double which could be in accurate becuase of rounding errors. I'm writing a program that draws graphs on a cartesian plane, so in order to go on the x-axis from say -2, to +2, in 20 intervals, i need one of these point to be zero or very close to it. how could i make sure i don't get rounding problems ? You can't. The only thing you can do is to compare your value of x to zero (using fcmp) and if it's close enough force it to be zero. Btw, Is the difference between 1e-16 and 0.0 so significant that it will show up on a graph in the range [-1,1] ? bye, gert Jul 22 '05 #11

 P: n/a heh, i also thaught of not worrying about it being 1e-16, but then there's a pixel missing where x is 0. Looks like i will have to make 2 loops and 1 statement. for when: x - epsilon() < 0 x = 0 x + epsilon() > 0 Gert Van den Eynde wrote: Corne' Cornelius wrote:i should've made it more clear what i actually want to do.I'm not really trying to compare 2 double which could be in accuratebecuase of rounding errors.I'm writing a program that draws graphs on a cartesian plane, so inorder to go on the x-axis from say -2, to +2, in 20 intervals, i needone of these point to be zero or very close to it.how could i make sure i don't get rounding problems ? You can't. The only thing you can do is to compare your value of x to zero (using fcmp) and if it's close enough force it to be zero. Btw, Is the difference between 1e-16 and 0.0 so significant that it will show up on a graph in the range [-1,1] ? bye, gert Jul 22 '05 #12

 P: n/a Hi! Corne' Cornelius writes: heh, i also thaught of not worrying about it being 1e-16, but thenthere's a pixel missing where x is 0. If you want to draw a point for every pixels you should loop over pixels and not over doubles. On the other hand, making small steps and drawing a straight line between these, is likely to be good enough. Furthermore, if you draw points for every pixel in the x-direction you should also worry about what happens if the slope of your graph is bigger than 1. Bye, Chris Dams Jul 22 '05 #13

 P: n/a Corne' Cornelius wrote: heh, i also thaught of not worrying about it being 1e-16, but then there's a pixel missing where x is 0. Then your transformation from world coordinates to pixel coordinates is in error, if such a small deviation from 0 makes that effect. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #14

 P: n/a Karl Heinz Buchegger wrote: Corne' Cornelius wrote: heh, i also thaught of not worrying about it being 1e-16, but then there's a pixel missing where x is 0. Then your transformation from world coordinates to pixel coordinates is in error, if such a small deviation from 0 makes that effect. The usual error is to truncate instead of round when chopping of the fractional part in pixel space. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #15

 P: n/a In message , Corne' Cornelius writesi should've made it more clear what i actually want to do.I'm not really trying to compare 2 double which could be in accuratebecuase of rounding errors.I'm writing a program that draws graphs on a cartesian plane, so inorder to go on the x-axis from say -2, to +2, in 20 intervals, i needone of these point to be zero or very close to it.how could i make sure i don't get rounding problems ? You can often improve matters by using an integer loop counter: instead of: for (double x=xstart; x

### This discussion thread is closed

Replies have been disabled for this discussion.