2

I tested this on a empty project and does not happen.

Description

As you can see the newValue becomes 2.98023e-08 when I subtract the bossPercentage value. This happens only when bossPercentage is 0.2f and the previous value is 0.2f. The difference should be 0.0f but I don't understand why I get 2.98023e-08 instead.

For reference, remainingBossPercentage is a property in [GameController] class defined as following:

//header
@property (readwrite, nonatomic) float remainingBossPercentage;
//.m
@synthetize remainingBossPercentage;
//init
remainingBossPercentage=1.0f;

I'd like to ask you inisght on what I may be doing that causes this error.

EDIT: I subtract 0.2f to remainingBossPercentage (for each boss enemy) and everything works fine until I reach the last enemy object that has again 0.2f and I get to the crucial point of doing 0.2f - 0.2f (screenshot below)

EDIT 2: I am greatful for all comments and answers, also the closing votes. What induced me to ask this question is the fact that newValue is 2.98023e-08. I now see that there are also comparison issues (thanks to the extremely useful QA linked by the people that voted to close the answer). What I wonder is.. why in my new test project with only 2 test variables this does not happen? (I created a HelloWorld project that substracts two floats).

I am asking this because, as one of the user suggests, is important to understand floating points without taking shourtcuts. YES, I am taking a shortcut by asking this question because I don't have time tonight to study it properly but I would like to try understanding and learning at the best I can. I will read the answers properly and dedicate my time to understand but if in the meanwhile I can I would like to add a doubt:

could it be that for memory management reasons the two projects (the test one and my actual game) beheave differently? Could the different beheaviour of the two projects somehow linked with memory being swapped in dirty areas? (e.g. the game having bigger memory usage gets swapped more and hence there may be a loss of precision?)

PS: I found out a question with exactly the same 2.98023e-08 value. What I still wonder is why this doesn't happen in the same test project (I am doing some more testing now).

mm24
  • 9,280
  • 12
  • 75
  • 170
  • While this is a legitimate question it has been asked in many forms before and received good answers. Please take a look at http://floating-point-gui.de/ and the other questions here and stop expecting floats to be precise. – Jonah Nov 26 '13 at 20:20
  • 1
    The only stupid question is the one you dont ask. Read, learn, keep asking. .02 – YvesLeBorg Nov 26 '13 at 21:20
  • 2
    do a test project with (sorry, cant add an answer to make this clear) : float c=1.0; c=c-.2;c=c-.2;c=c-.2;c=c-.2; CCLOG(@"%.12f",c); the console should log -> main : 0.200000032783 <- , ie the floating point value accuracy you are getting depends on 'how' you get to it. If you do : float a=.2; float b=.2; float c=a-b; and log, you will get ->main : 0.000000000000 <-. – YvesLeBorg Nov 26 '13 at 22:06

1 Answers1

1

Simply, floating point numbers should not be expected to be completely accurate.

Floating point numbers (as used in our usual computers) are natively in base 2, out usual number is base 10. Not all numbers in one number base can be expressed with full accuracy in another number base.

As an empale 1/3 can not be expressed with complete accurate in the base 10 number system (0.333333...) but can be in the base 3 number system.

The upshot, one needs to compare floating point numbers with a specified error range. Take the absolute value of the difference and compare that to the allowable range.

Because of this financial amounts are generally not (should not be) expressed as floating point numbers. This give rise to classes such as NSDecimalNumber.

zaph
  • 111,848
  • 21
  • 189
  • 228
  • It is not generally good to advise people to compare floating-point numbers within a specified error range. This either reduces false negatives at the expense of increasing false positives or vice-versa. Without knowing the requirements of a particular application, you cannot know whether this trade-off improves the situation or is acceptable. Therefore, it is bad advice. Proper advice is that software engineers planning to use floating-point **must** understand it and **must** design accordingly. They should not take shortcuts. – Eric Postpischil Nov 26 '13 at 21:29
  • The best advice might be not to get oneself into such a situation. In some cases it is necessary, an example is `XCTAssertEqualsWithAccuracy (a1, a2, accuracy, format…)`. – zaph Nov 26 '13 at 21:38
  • 1
    In this case, the best advice is probably to just use an integer between, say, 0 and 100. – Jesse Rusak Nov 26 '13 at 21:47