iphone – 正确的方法来实例化一个NSDecimalNumber从float或double

iphone – 正确的方法来实例化一个NSDecimalNumber从float或double,第1张

概述我正在寻找最好的方式来实例化NSDecimalNumber从双或短。有以下NSNumber类和实例方法… +NSNumber numberWithFloat+NSNumber numberWithDouble-NSNumber initWithFloat-NSNumber initWithDouble 但是这些似乎返回NSNumber。另一方面,NSDecimalNumber定义如下: +N 我正在寻找最好的方式来实例化NSDecimalNumber从双或短。有以下NSNumber类和实例方法…

+NSNumber numberWithfloat+NSNumber numberWithDouble-NSNumber initWithfloat-NSNumber initWithDouble

但是这些似乎返回NSNumber。另一方面,NSDecimalNumber定义如下:

+NSDecimalNumber decimalNumberWithMantissa:exponent:isNegative:+NSDecimalNumber decimalNumberWithDecimal:

这里有几种可能性。如果您将NSDecimalNumber设置为上述NSNumber方便方法的返回值,Xcode会生成警告。

将欣赏输入的最干净,正确的方式去…

解决方法 你在正确的轨道上(注意,见下文)。你应该能够使用来自NSNumber的初始化器,因为它们是NSDecimalNumber继承的。

NSDecimalNumber *floatDecimal = [[[NSDecimalNumber alloc] initWithfloat:42.13f] autorelease];NSDecimalNumber *doubleDecimal = [[[NSDecimalNumber alloc] initWithDouble:53.1234] autorelease];NSDecimalNumber *intDecimal = [[[NSDecimalNumber alloc] initWithInt:53] autorelease];NSLog(@"floatDecimal floatValue=%6.3f",[floatDecimal floatValue]);NSLog(@"doubleDecimal doubleValue=%6.3f",[doubleDecimal doubleValue]); NSLog(@"intDecimal intValue=%d",[intDecimal intValue]);

更多信息关于这个问题可以找到here。

但是,我已经看到很多关于Stack Overflow和网络上有关初始化NSDecimalNumber的问题的讨论。似乎有一些问题与精度和转换/从NSDecimalNumber双打。特别是当你使用从NSNumber继承的初始化成员。

我敲了下面的测试:

double dbl = 36.76662445068359375000;ID xx1 = [NSDecimalNumber numberWithDouble: dbl]; // Don't do thisID xx2 = [[[NSDecimalNumber alloc] initWithDouble: dbl] autorelease];ID xx3 = [NSDecimalNumber decimalNumberWithString:@"36.76662445068359375000"];ID xx4 = [NSDecimalNumber decimalNumberWithMantissa:3676662445068359375L exponent:-17 isNegative:NO];NSLog(@"raw doubleValue: %.20f,%.17f",dbl,dbl);NSLog(@"xx1 doubleValue: %.20f,description: %@",[xx1 doubleValue],xx1);   NSLog(@"xx2 doubleValue: %.20f,[xx2 doubleValue],xx2);   NSLog(@"xx3 doubleValue: %.20f,[xx3 doubleValue],xx3);   NSLog(@"xx4 doubleValue: %.20f,[xx4 doubleValue],xx4);

输出为:

raw doubleValue: 36.76662445068359375000               36.76662445068359375xx1 doubleValue: 36.76662445068357953915,description: 36.76662445068359168xx2 doubleValue: 36.76662445068357953915,description: 36.76662445068359168xx3 doubleValue: 36.76662445068357953915,description: 36.76662445068359375xx4 doubleValue: 36.76662445068357953915,description: 36.76662445068359375

所以你可以看到,当在NSNumber使用numberWithDouble方便的方法(你不应该真正使用,因为它返回错误的指针类型),甚至初始化initWithDouble(IMO“应该”可以调用)你得到一个NSDecimalNumber与通过调用decimalNumberWithString:或decimalNumberWithMantissa:exponent:isNegative:时获得的内部表示(通过调用对象上的描述返回)不一样精确。

另外,注意,通过调用doubleValue在NSDecimalNumber实例转换回double失去精度,但有趣的是,无论你调用什么初始化都是一样的。

所以,最后,我认为建议您使用在NSDecimalNumber类级别声明的一个decimalNumberWith *方法来创建您的NSDecimalNumber实例,当处理高精度浮点数。

那么,当你有一个双,浮动或其他NSNumber时,你如何轻松地称这些初始化?

两种方法描述here“工作”,但仍然有精度问题。

如果你已经把号码存储为NSNumber,那么这应该工作:

ID n = [NSNumber numberWithDouble:dbl];ID dn1 = [NSDecimalNumber decimalNumberWithDecimal:[n decimalValue]];NSLog(@"  n doubleValue: %.20f,[n doubleValue],n);   NSLog(@"dn1 doubleValue: %.20f,[dn1 doubleValue],dn1);

但正如你可以从下面的输出中看到的,它会丢失一些不太显着的数字:

n doubleValue: 36.76662445068359375000,description: 36.76662445068359dn1 doubleValue: 36.76662445068357953915,description: 36.76662445068359

如果数字是一个原始(float或double),那么这应该工作:

ID dn2 = [NSDecimalNumber decimalNumberWithMantissa:(dbl * pow(10,17))                                          exponent:-17                                         isNegative:(dbl < 0 ? YES : NO)];NSLog(@"dn2 doubleValue: %.20f,[dn2 doubleValue],dn2);

但是你会再次得到精度错误。正如你可以在下面的输出中看到的:

dn2 doubleValue: 36.76662445068357953915,description: 36.76662445068359168

我认为这种精度损失的原因是由于涉及浮点乘法,因为下面的代码工作正常:

ID dn3 = [NSDecimalNumber decimalNumberWithMantissa:3676662445068359375L                                            exponent:-17                                          isNegative:NO];NSLog(@"dn3 doubleValue: %.20f,[dn3 doubleValue],dn3);

输出:

dn3 doubleValue: 36.76662445068357953915,description: 36.76662445068359375

因此,从双精度或浮点到NSDecimalNumber最一致精确的转换/初始化是使用decimalNumberWithString :.但是,正如Brad larson在他的答案中指出的,这可能有点慢。他的技术使用NSScanner转换可能更好,如果性能成为一个问题。

总结

以上是内存溢出为你收集整理的iphone – 正确的方法来实例化一个NSDecimalNumber从float或double全部内容,希望文章能够帮你解决iphone – 正确的方法来实例化一个NSDecimalNumber从float或double所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1045888.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存