views:

514

answers:

4

Two quick questions if I may, is this how I should go about taking two NSNumber objects, performing a calculation and ending up with a result that is also an NSNumber?

NSNumber *flux = [[NSNumber alloc] initWithDouble:100.0];
NSNumber *mass = [[NSNumber alloc] initWithDouble:3];

double intermediate = [flux doubleValue] / [mass doubleValue];
NSLog(@"INTER : %.20f", intermediate);

NSNumber *result = [[NSNumber alloc] initWithDouble:intermediate];
NSLog(@"RESULT: %@", result);

...
...

[flux release];
[mass release];
[result release];

Also looking at the results in console from NSLog, is there any loss of precision? I would assume there is not and what I am seeing is just display precision, but just curious?

INTER : 33.33333333333333570181
RESULT: 33.33333333333334

gary

+2  A: 

Using %@ means that NSLog will send a description method to the parameter, and it will use its description in the output. Whatever NSNumber decides is enough precision for a description is the number you will see in NSLog. If you did:

NSLog ("%.20f", [result doubleValue]);

It should produce the same output as the NSLog with intermediate.

dreamlax
I can't test this though, I'm just guessing here.
dreamlax
+1  A: 

Internally the NSNumber will format its content with:

  • double: %0.16g
  • float: %0.7g

But you're specifying to use 20 digits after the decimal point, which surely doesn't match the description.

Also, the precision of double is only about 16 digits. All digits beyond it are garbage (in base-10).

KennyTM
+3  A: 

(Tangential to your question but related)

NSNumber isn't intended to do base-10 math with. It's largely there to wrap and store numerical values. If you need to do real math, you want to use a NSDecimal.

NSDecimalNumber, an immutable subclass of NSNumber, provides an object-oriented wrapper for doing base-10 arithmetic. An instance can represent any number that can be expressed as mantissa x 10^exponent where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from –128 through 127

Despite the fact that we call them "computers" our logic engines can't do actual math so they have to fake it. When you get to the extremes of very large or very small magnitude numbers, that faking begins to show. That is why you need custom numerical classes that can hold more information than just a string of digits.

So, if you have any concerns about precision, use NSDecimal instead of NSNumber. NSDecimal is designed to perform precise calculations.

Edit01:

... how I should go about taking two NSNumber objects, performing a calculation and ending up with a result that is also an NSNumber?

Strictly speaking, you should not use NSNumber for calculations. You will notice that NSNumber has no dedicated methods for doing math. You have to convert to scalar and then back again to an object. This causes a loss of precision and the precision can change depending on the hardware or the definitions of the scalars.

NSDecimal by contrast can precisely represent very precise numbers because it holds them abstractly. It has dedicated methods for performing precise mathematical operations.

Also looking at the results in console from NSLog, is there any loss of precision?

Yes, there is a loss of mathematical precision beyond just the formatting. Scalars have different precision depending on their type and size of the number they store.. At large magnitudes, this causes problems with precision. If you mix types, say a NSInteger and a NSUInteger, you get the maximal precision of the NSInteger.

You also run into all the old problems of using scalars.

If you ask an NSNumber object for its value using a type that cannot hold the value, you get back an erroneous result—for example, if you ask for the float value of a number created with a double that is greater than FLT_MAX, or the integer value of a number created with a float that is greater than the maximum value of NSInteger.

NSDecimal frees you from all these possible sources of error. It does precise mathematical calculations up to magnitudes way beyond what anyone would use in the real world.

I repeat: If precision is a concern, don't use NSNumber or scalar.

TechZen
I believe you've misinterpreted the question.
Georg
More like I went off on a tangent. I edited to clarify.
TechZen
Thank you, its good to know about NSDecimal, I will have a look.
fuzzygoat
@Georg. I believe TechZen has given a perfectly satisfactory answer. Just because a question is about NSNumber doesn't mean that a better solution shouldn't be provided.
Abizern
A: 

NSNumbers and other NSValues are just object wrappers around primitive values. The object will contain whatever you put into it, as determined by how you created it.

Peter Hosey