2010-02-25 140 views
3

如果我可能会提出两个简单的问题,那么我应该如何处理两个NSNumber对象,执行计算并最终得到一个也是NSNumber的结果?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]; 

另外从NSLog看在控制台的结果,是否有任何精度损失?我会假设没有,我所看到的只是显示精度,但只是好奇?

INTER : 33.33333333333333570181 
RESULT: 33.33333333333334 

加里

回答

14

(切向你的问题,但相关的)

的NSNumber不打算做基10数学与。它主要用于包装和存储数值。如果你需要做真正的数学,你想用一个NSDecimal.

NSDecimalNumber,一个不变的子类的NSNumber的 ,提供了一个 面向对象的包装做 基地10算术。一个实例可以 表示任何数量,可以是 表示为尾数×10 ^指数 其中尾数是十进制整数高达 至38位长,和指数是从-128的整数 通过127

尽管我们称他们为“电脑”的事实,我们的逻辑引擎不能做真正的数学运算,所以他们必须伪造它。当你达到非常大或非常小的数量级的极端时,伪装就开始显现。这就是为什么你需要自定义的数字类,可以容纳更多的信息,而不仅仅是一串数字。

因此,如果您对精度有任何疑问,请使用NSDecimal而不是NSNumber。 NSDecimal旨在执行精确的计算。

Edit01:

...我应该如何去取两个 NSNumber对象,执行 计算,并以 结果也是一个NSNumber?

严格地说,你不应该使用NSNumber进行计算。你会注意到NSNumber没有专门的数学方法。您必须转换为标量,然后再转回到对象。这会导致精度损失,并且精度可能会根据硬件或标量的定义而改变。

NSDecimal通过对比可以精确地表示非常精确的数字,因为它可以抽象地保存它们。它具有执行精确数学运算的专用方法。

也在寻找从NSLog的控制台 的结果,是那里 精度损失?

是的,除了格式化之外,还有数学精度的损失。标量具有不同的精度,这取决于它们存储的数量和类型的大小。在大数量级上,这会导致精度问题。如果你混合使用类型,比如说一个NSInteger和一个NSUInteger,你会得到NSInteger的最大精度。

也碰到所有old problems of using scalars.

如果您使用的是不能持有 的价值,你回来的错误 结果 - 例如,一个类型要求其 值一个NSNumber对象,如果你请求用 double创建的数字的浮点值大于FLT_MAX, 或使用比最大值大于 的浮点数创建的数字 的整数值大于NSInteger的最大值。

NSDecimal让你摆脱所有这些可能的错误来源。它以精确的数学计算达到超出任何人在现实世界中使用的程度。

我重复一遍:如果精度是一个问题,请不要使用NSNumber或标量。

+0

我相信你误解了这个问题。 – 2010-02-25 12:32:29

+0

更像是我在一条正切线上。我编辑澄清。 – TechZen 2010-02-25 12:36:57

+0

谢谢,很高兴知道NSDecimal,我会看看。 – fuzzygoat 2010-02-25 13:48:34

2

使用%@意味着NSLog将发送description方法的参数,并且将使用其描述在输出中。不管NSNumber决定是否足够精确的描述是你会在NSLog看到的数字。如果你做了:

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

应该产生的输出为NSLogintermediate相同。

+0

虽然我无法测试,但我只是在这里猜测。 – dreamlax 2010-02-25 12:07:06

0

NSNumbers和其他NSValues只是原始值周围的对象包装。该对象将包含您放入它的任何内容,具体取决于您是如何创建它的。