如果可能的话,有两个简单的问题,这就是我应该如何处理两个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
加里
答案 0 :(得分:14)
(与您的问题相关但相关)
NSNumber不打算用10进行数学运算。它主要用于包装和存储数值。如果您需要进行真正的数学计算,则需要使用NSDecimal.
NSDecimalNumber,一个不可变的子类 NSNumber,提供了一个 做面向对象的包装器 基数为10的算术。一个实例可以 代表任何可以的数字 表示为尾数x 10 ^指数 其中尾数是十进制整数 到38位数,指数是一个 -128到127之间的整数
尽管我们称它们为“计算机”,但我们的逻辑引擎无法进行实际数学计算,因此必须伪造它。当你达到非常大或非常小的数字的极端时,这种假装开始显现。这就是为什么你需要自定义数字类来保存更多信息而不仅仅是一串数字。
因此,如果您对精度有任何疑虑,请使用NSDecimal而不是NSNumber。 NSDecimal旨在执行精确计算。
Edit01:
......我应该怎么做两个 NSNumber对象,执行一个 计算并以a结尾 结果也是一个NSNumber?
严格来说,您不应该使用NSNumber进行计算。您会注意到NSNumber没有专门的数学方法。您必须转换为标量然后再返回到对象。这会导致精度损失,并且精度可能会根据硬件或标量的定义而改变。
相比之下,NSDecimal可以精确地表示非常精确的数字,因为它抽象地保留它们。它有专门的方法来执行精确的数学运算。还在控制台中查看结果 来自NSLog,是否有任何损失 精度?
是的,除了格式化之外,还有数学精度的损失。标量具有不同的精度,具体取决于它们的类型和存储数量的大小。在较大的范围内,这会导致精度问题。如果混合类型,比如NSInteger和NSUInteger,则可以获得NSInteger的最大精度。
您也会遇到所有old problems of using scalars.
如果你问一个NSNumber对象 使用无法保持的类型的值 价值,你得到一个错误的 结果 - 例如,如果你要求 用a创建的数字的浮点值 双倍大于FLT_MAX, 或数字的整数值 用更大的浮点数创建 超过NSInteger的最大值。
NSDecimal使您摆脱所有这些可能的错误来源。它可以进行精确的数学计算,其大小超出任何人在现实世界中的使用范围。
我再说一遍:如果需要考虑精度,请不要使用NSNumber或标量。
答案 1 :(得分:4)
NSNumber内部将format its content with:
%0.16g
%0.7g
但是您指定在小数点后使用20位数,这肯定与描述不符。
此外,the precision of double is only about 16 digits。超出它的所有数字都是垃圾(基数为10)。
答案 2 :(得分:2)
使用%@
表示NSLog
会向参数发送description
方法,并在输出中使用其描述。无论NSNumber
决定哪种描述足够精确,您都会在NSLog
中看到这个数字。如果你这样做了:
NSLog ("%.20f", [result doubleValue]);
它应该与NSLog
生成与intermediate
相同的输出。
答案 3 :(得分:0)
NSNumber和其他NSValues只是原始值的对象包装器。该对象将包含您放入其中的任何内容,具体取决于您创建它的方式。