2
NSDecimalNumber *minVal = [NSDecimalNumber decimalNumberWithString:@"0.0"];
NSDecimalNumber *maxVal = [NSDecimalNumber decimalNumberWithString:@"111.1"];
NSDecimalNumber *valRange = [maxVal decimalNumberBySubtracting:minVal];
CGFloat floatRange = [valRange floatValue];
NSLog(@"%f", floatRange); //prints 111.099998

Isn't NSDecimalNumber supposed to be able to do base-10 arithmetic correctly?

DTs
  • 1,196
  • 1
  • 11
  • 28

3 Answers3

3

Yes, NSDecimalNumber operates in base-10, but CGFloat doesn't.

PengOne
  • 48,188
  • 17
  • 130
  • 149
  • I'm not performing any arithmetic operation on `CGFloat` – DTs Dec 13 '11 at 22:58
  • no, but you are getting the float value and logging as a float. Float does not have the capacity to display certain exact numbers. Obviously 111.100000 is one of them – coneybeare Dec 13 '11 at 23:09
  • 1
    `floatValue` does (btw, you should probably use `doubleValue` instead as it's the preferred method in [`NSDecimalNumber`](http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDecimalNumber_Class/Reference/Reference.html)) – PengOne Dec 13 '11 at 23:11
  • From Apple's documentation: doubleValue "Returns the **approximate** value of the receiver as a double." – zaph Dec 13 '11 at 23:38
  • ok, just doing that `CGFloat aNumber = 111.1;` shows as `111.099998` in the debugger even before any operation has been performed on it. Thanks guys. – DTs Dec 13 '11 at 23:45
1

Yes, NSDecimalNumber is base-10.

Converting to a floating point type will can loose accuracy. In their case since the example just used NSLog just NSLog the NSDecimalNumber:

NSDecimalNumber *minVal = [NSDecimalNumber decimalNumberWithString:@"0.0"];
NSDecimalNumber *maxVal = [NSDecimalNumber decimalNumberWithString:@"111.1"];
NSDecimalNumber *valRange = [maxVal decimalNumberBySubtracting:minVal];
CGFloat floatRange = [valRange floatValue];
NSLog(@"floatRange: %f", floatRange);
NSLog(@"valRange: %@", valRange);

NSLog output:

floatRange: 111.099998
valRange: 111.1
zaph
  • 111,848
  • 21
  • 189
  • 228
0

OK, just doing that CGFloat aNumber = 111.1; shows as 111.099998 in the debugger, even before any operation has been performed on it. Therefore the precision is lost right when it is assigned to the less precise data type, regardless of any arithmetic operations occurring later.

DTs
  • 1,196
  • 1
  • 11
  • 28