1
float yLimit = [[UIScreen mainScreen] bounds].size.height;
yLimit = yLimit * (2/3);
NSLog(@"ylimit: %f", yLimit);

the nslog yields 0.0.

Huh?

quantumpotato
  • 9,637
  • 14
  • 70
  • 146
  • Try putting f or F after the 2 and after the 3 – uchuugaka Jan 13 '15 at 04:25
  • 2
    Or change 3 to 3.0. `yLimit *= 2/3.0:` – rmaddy Jan 13 '15 at 04:33
  • BTW - Use `CGFloat`, not `float`. – rmaddy Jan 13 '15 at 04:34
  • The reason @rmaddy says this, is because CGFloat is conditionalized to be a float or double as appropriate on 32 and 64 bit systems respectively, and UIKit and AppKit measure coordinates using CGFloat. In fact, you are probably ignoring some warnings somewhere because Clang in Xcode will nag you for implicit conversions with loss of precision usually. – uchuugaka Jan 13 '15 at 05:21
  • possible duplicate of [Converting Fahrenheit to Celsius in C](http://stackoverflow.com/questions/4890480/converting-fahrenheit-to-celsius-in-c) – tmyklebu Jan 13 '15 at 10:39

2 Answers2

6

In other words the 2 and 3 are implicitly integer types. When the ⅔ division occurs you get integer division. Zero. No remainder. No rounding.

Then you multiply a float be that result.

The lesson here is that you should explicitly type your literals. C has suffixes for literals to help you with this.

It's actual intended as much for the human reading code as it is for the compiler.

uchuugaka
  • 12,679
  • 6
  • 37
  • 55
1

Change your code from

yLimit = yLimit *(2/3);

to

yLimit = yLimit *2/3;

When the 2/3 division occurs you get 0. (Zero) then 0 multiplied by yLimit yields 0

2/3 is equivalent to Int/Int which results in an Int instead of Double or Float which the questioner was expecting.

Well, yLimit * (2/3) results to yLimit * 0, as 2/3 = 0.6666666667, but it round off to 0 due to implicitly integer types

aashish tamsya
  • 4,903
  • 3
  • 23
  • 34
  • I was about to point out that this makes no difference but it actually does. You should explain why this works. – rmaddy Jan 13 '15 at 04:48
  • 1
    @FahimParkar Same here what? You were going to say the same thing as me or do you want to know why it works? I know why, I just want to give the poster a chance to explain it. – rmaddy Jan 13 '15 at 04:56
  • 1
    @rmaddy : same abt this point *I was about to point out that this makes no difference but it actually does.* I was about to downvote, but it works.. and its working bcz it will behave like `(yLimit*2)/3` – Fahim Parkar Jan 13 '15 at 05:09
  • 2
    The reason this works is that `yLimit * 2 / 3` is the same as `(yLimit * 2) / 3`. The `yLimit * 2` is comprised of a `float` and an `int`. The `int` is promoted to `float` and the result of the multiplication is a `float` value. Then the division is done with the `float` and `int` (`3`). Same thing. The `int` is promoted to `float` and the result of `float / float` is a `float`. But the original code does `2 / 3` first. This is `int / int` which gives an `int` result (`0`). Then the `float` (`yLimit`) is multiplied by the `0` (after being promoted to `float`). And anything times `0` is `0`. – rmaddy Jan 13 '15 at 05:13
  • Rather than being clever though, it is much better to resolve the issue the human experienced with this in the first place, use explicit literal suffixes or casts to ensure that the intent of the code is clear. – uchuugaka Jan 13 '15 at 05:17
  • Why do you quote my post verbatim? At least edit the words a little. – uchuugaka Jan 13 '15 at 05:19
  • @FahimParkar yes, we have to include yLimit in one of the operation so as to include a vaild result – aashish tamsya Jan 13 '15 at 05:19
  • 1
    Removing the parens works because of the operator precedence in C. with * multiplication and / division in this statement, C will evaluate from left to right just like you read it. – uchuugaka Jan 13 '15 at 05:23
  • But that said, it's almost always bad coding style IMHO to rely on operator precedence side effects rather than writing clear and explicit code. – uchuugaka Jan 13 '15 at 05:24
  • @uchuugaka Removing the parens makes it work because it changes the order of evaluation in just the right way to allow the variable types to be promoted differently than when evaluated in the original order. I'm not saying this is a clear or better answer, simply explaining why it works. – rmaddy Jan 13 '15 at 05:24
  • No worries! Adding Value man! Well it's what I meant to say, but yes that's a little more clear, ironically, I seem to always forget to explicitly mention the "promotion" (implicit casting). But yeah, it's the order of evaluation changing the behavior of evaluation of operands. But totally hate that kind of coding because then everyone has to be wary of side-effects they didn't notice. – uchuugaka Jan 13 '15 at 06:09