6

I really like the new literals in Objective-C. I am wondering if with the new additions there's a better way to compare numbers.

For example, if I want to compare a and b:

a = @1;
b = @2;

Is the only way to compare them like this:

[a intValue] > [b intValue]

Or are there better, more elegant, solutions?

jscs
  • 63,694
  • 13
  • 151
  • 195
0xSina
  • 20,973
  • 34
  • 136
  • 253
  • If you want, you could write a category adding methods like `[a greaterThan: b]` and `[a equalTo: b]` – pasawaya Sep 11 '12 at 02:47
  • It's possible that compiler rewriting of operators will eventually emerge as an extension of this number literal syntax. `@1` already becomes `[NSNumber numberWithInt:1]` -- there's no reason that `@1 > @2` couldn't be allowed and rewritten as `[@1 isGreaterThan:@2]` (well, no reason aside from possible confusion: "Why can't I do `if( 1 > @2 )`?"). – jscs Sep 11 '12 at 03:03
  • yea you're right, it would take away low level pointer comparisons...but they could always do something like @1 @>= @2 and then implement greaterThanOrEqualTo in NSNumber, so it would be translated as [@1 greaterThanOrEqualTo:@2]...this way you can keep your pointer arithmetic as well as logical comparisons – 0xSina Sep 11 '12 at 03:05
  • Or they could ditch the whole silly idea of boxing raw types and just go back to using `int` :-) – paxdiablo Sep 11 '12 at 03:09

4 Answers4

13

For equality checks, you can use isEqualToNumber which checks if either the id or content is equal (with the latter using compare):

if ([a isEqualToNumber:b])                  // if a == b

Not sure why they also didn't implement isGreaterThanNumber and isLessThanNumber convenience methods (and possibly >= and <= as well), since the compare method below seems a little clunky.

For inequality checks, just use compare directly (you can also do this for equality as can be seen from the first one below):

if ([a compare:b] == NSOrderedSame)         // if (a == b)
if ([a compare:b] == NSOrderedAscending)    // if (a <  b)
if ([a compare:b] == NSOrderedDescending)   // if (a >  b)

if ([a compare:b] != NSOrderedSame)         // if (a != b)
if ([a compare:b] != NSOrderedAscending)    // if (a >= b)
if ([a compare:b] != NSOrderedSescending)   // if (a <= b)

Details can be found on the NSNumber class documentation page.


Keep in mind there's nothing preventing you from creating your own helper function which would, for example, allow code like:

if (nsnComp1 (a, ">=", b)) ... // returns true/false (yes/no)

or:

if (nsnComp2 (a, b) >= 0)  ... // returns -1/0/+1

even though it's less Objective-C and more C :-) It depends on whether your definition of "elegant" is bound mostly by efficiency or readability. Whether that's preferable to your intValue option is a decision you'll need to make yourself.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Well, the probably only added `isEqualToNumber:` because the `isEqualTo...` methods are used in many other places [like `isEqualToString:`]. Just IMHO. – Mazyod Sep 11 '12 at 02:18
  • Thanks...didn't know about the compare, but still you don't know >= or<= ....would be more awesome if they did @1 == @2...but i understand why not. – 0xSina Sep 11 '12 at 03:02
  • 1
    @0xSina, if you mean I haven't specified an easy way to do `>=` and `<=` with `compare`, see the update. Those two, along with `!=`, can be done with the `!=` comparison operator. – paxdiablo Sep 11 '12 at 06:05
  • Ah well played. I feel dumb right now, didn't think of that :) – 0xSina Sep 11 '12 at 23:54
7

NSNumber implements -compare: (as do a number of other classes). So you can say

switch ([a compare:b]) {
    case NSOrderedAscending: // a < b
        // blah blah
        break;
    case NSOrderedSame: // a == b
        // blah blah
        break;
    case NSOrderedDescending: // a > b
        // blah blah
        break;
}
Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
0

NSNumber also has an isEqualToNumber:

Zhang
  • 11,549
  • 7
  • 57
  • 87
0

Here is the code snippet to check which works good:

NSLog(@"%d", number1 == number2);
NSLog(@"%d", [number1 isEqual:number2]);
NSLog(@"%d", [number1 isEqualToNumber:number2]);

The output:

1
1
1

Conclusion:

To understand comparison, you need to understand instance allocation. NSNumber internally implements a cache of objects assigned, and maps existing objects to any newly created objects using values. If an existing NSNumber object is found holding value 1, no new NSNumber instance is created.

Nirav Bhatt
  • 6,940
  • 5
  • 45
  • 89