Allegro.cc Forums » Programming Questions » ((0.1f - 0.1f) == (0.1f - 0.1)) == false

Credits go to Hard Rock for helping out!
 Timorg Member #2,028 March 2002 I have been working on a program and I came across a problem, in the program I had a variable that should have a value between 0 and 1, with keys making the value step 0.1 a time, but I found the down step from 0.1 to 0 wasn't working correctly.This is the small code snippet that demonstrate the problem.#include int main(int argc, char *argv[]) { std:: cout << (0.1f - 0.1f) << " = " << (0.1f - 0.1) << std::endl; return 0; }  I have tried this code ong++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-56)g++ (GCC) 3.4.2 (mingw-special)MSVC8 (Version 14.00.50727.42 for 80x86)and I get the same results in each.0 = 1.49012e-09  So I guess my question is, what am i misunderstanding, my current solution is to not allow the user to change that value, and work around the issue. But I wish I had a better solution.-Tim ____________________________________________________________________________________________"c is much better than c++ if you don't need OOP simply because it's smaller and requires less load time." - alethiophileOMG my sides are hurting from laughing so hard... :D
 Carrus85 Member #2,633 August 2002 Just as an elaboration on what Hard Rock posted above, here is an in-depth explanation of why this happens.First, 1/10th is a repeating decimal in base 2 (just like 1/3, 1/6, 1/9, etc. in base 10). Illustration:Long division of 1/3  0.33 3 | 1.00 -9 10 -9 1... goes on forever (sorry, it isn't horribly readable...  Long division of 1/10 in base 2  0.00011001 1010 | 1.00000000 - 1010 = 1100 -1010 = 10000 ... at this point we have hit a cycle; we will never resolve this evenly. - 1010 = 110  In short, just like , Now, as for why you get that weird number for 0.1 - 0.1, first, lets write out the actual IEEE754 float and double representations being used for these values (the first one is assumed, hence the parenthesis, and using round to nearest even, for those interested)float: 0 01111100 (1)10011001100110011001101 (1.1001100... * 2^-4) double: 0 01111111100 (1)1001100110011001100110011001100110011001100110011010Subtract these two: (digits in ()'s are gaurd digits to prevent funky rounding; not really necessary here though) 1.10011001100110011001101 (000) -1.1001100110011001100110011001100110011001100110011010 (000) (which, can be rewritten as this) 1.1111111111111111111111 (carries) 1.10011001100110011001101 00000000000000000000000000000 (000) (extended to double) + 0.01100110011001100110011 00110011001100110011001100110 (000) (Using 2's compliment) = 0.00000000000000000000000 00110011001100110011001100110 (000) * 2 ^ -4 = (1.10011001100110011001100110 * 2 ^ -30 using double.) = (1.10011001100110011001101 * 2 ^ -30 using float accuracy. (rounded))  If you convert this result (the double) back to base 10, we arrive at , which, guess what, is when rounded.Probably a bit longer of an explanation than necessary, but hey, information never hurts.EDIT: flipped a 6 to a 9 (GHA!)