11

I'm trying to calculate some numbers in an iPhone application.

int i = 12;
int o = (60 / (i * 50)) * 1000;

I would expect o to be 100 (that's milliseconds) in this example but it equals 0 as displayed by NSLog(@"%d", o).

This also equals 0.

int o = 60 / (i * 50) * 1000;

This equals 250,000, which is straight left-to-right math.

int o = 60 / i * 50 * 1000;

What's flying over my head here?

Thanks,
Nick

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
Stateful
  • 737
  • 2
  • 9
  • 25
  • 3
    See [C problem - division result is always zero ](http://stackoverflow.com/questions/2345902/c-problem-division-result-is-always-zero). – Matthew Flaschen Nov 16 '10 at 18:57

7 Answers7

20

In Objective-C / performs integer division on integer arguments, so 4/5 is truncated to 0, 3/2 is truncated to 1, and so on. You probably want to cast some of your numbers to floating-point forms before performing division.

You're also running in to issues with precedence. In the expression

60 / (i * 50) * 1000

the term inside the parentheses is calculated first, so 60 is divided by 600 which produces the result 0. In

60 / i * 50 * 1000

the first operation is to divide 60 by 12 which gives the result 5 and then the multiplications are carried out.

High Performance Mark
  • 77,191
  • 7
  • 105
  • 161
  • 3
    C too, of course. Arithmetic in Objective-C is identical to arithmetic in C. :) – Jonathan Grynspan Nov 16 '10 at 18:58
  • 6
    Strictly speaking, the result is not rounded, it is truncated. – Dima Nov 16 '10 at 18:59
  • 1
    Well, truncation is a form of rounding (toward zero) so... yeah. – Jonathan Grynspan Nov 16 '10 at 19:03
  • 4
    @Jonathan Sorry, but it helps to be precise about these things. Truncation is a form of rounding the same way integer division is a form of floating-point division. Not knowing the difference can get you into trouble, as you can see. – Dima Nov 16 '10 at 19:08
  • @Dima, truncation is a sort of rounding, also named as rounding toward zero. – Vovanium Nov 16 '10 at 20:01
  • @Vovanium and integer division is a sort of division, but if you do not keep in mind exactly what kind of division it is you may get unexpected results. Round off is defined as rounding up if the fractional part is greater than or equal to .5, and rounding down otherwise. Truncation is rounding down to the nearest integer, aka the "floor" operation. Rounding up to the nearest integer is called the "ceiling" operation. These three operations are related, but they are quite distinct. The result of integer division is the "floor", aka truncation, aka rounding down, not round off or round up. – Dima Nov 16 '10 at 20:12
  • 1
    @Dima: Trucation is equivalent to floor only for unsigned. Compare: floor(-5./2.) and -5/2. First will be -3., but second is -2. Truncation AKA round to zero if floor for positives, but ceil for negatives. That's detail, but it may foul up you. – Vovanium Nov 16 '10 at 21:00
  • Good point! Didn't realize that. Then truncation is neither round off, nor floor, nor ceiling. Спасибо. – Dima Nov 16 '10 at 21:07
  • 1
    see http://en.wikipedia.org/wiki/Rounding#Rounding_to_integer for terminology, and yes, truncation is a form of rounding – Christoph Nov 16 '10 at 22:44
4

An integer divided by an integer is an integer.

so 60/600 is not 0.1, it is 0.

Cast (or declare) some stuff as float instead.

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • 1
    Casting or introducing an implicit conversion to `float` or `double` is **not** the way to evaluate integer expressions. On systems without IEEE floating point, it could give very bogus results (C makes almost no requirements about the quality of floating point implementation) and even with IEEE floating point, you may get errors from loss of precision with integers too large to fit in the floating point type used. The correct solution to OP's problem is simply to algebraically simplify the expression. – R.. GitHub STOP HELPING ICE Nov 16 '10 at 19:36
1

It's doing integer math. 60 / (12 * 50) is 0.1, truncates to 0.

Should work if you force floating point and then cast back to an integer.

int o = (int)(60.0 / ((double) i / 50.0) * 1000.0;

Probably not really necessary to make everything a double.

Neth
  • 439
  • 4
  • 13
1

Replace:

int o = (60 / (i * 50)) * 1000;

with:

int o = 1200/i;
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 1
    Whoever the downvoter is, please explain yourself. Unlike the other answers, this answer gives the exact truncated-integer result of the computation, without any corner-cases due to overflow or loss of precision. As far as I can tell it's the only correct answer here. – R.. GitHub STOP HELPING ICE Nov 16 '10 at 20:35
0

I think you need to use float here instead of int. It will work the way you want! Will give you answer in decimals as well.

Mosib
  • 1
  • While `float` will work, that doesn't address the misunderstanding that caused the problem in the first place! – Andrew Oct 29 '12 at 12:39
0

By order of precedence, the operation:

60 / (12 * 50) 

is performed before multiplying by 1000.

This value is less than 1 and is cast to an int, which truncates it to 0. And 0 times anything is 0.

Use a float or first multiply by 1000 to ensure you're not ending up with propagating a 0 in your calculations.

Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
0

All the operations in your expression are performed in integer arithmetic, meaning that the fractional part of each intermediate result is truncated. This means that if you divide a smaller integer by a larger integer you will always get 0.

To get the result you want you must either make sure the operations are performed in a particular order, or you must use floats. For example the result of

int o = (60.0 / (i * 50.0)) * 1000.0;

should be o = 100.

Dima
  • 38,860
  • 14
  • 75
  • 115