NSNumberFormatter,NSDecimalNumber和Scientific Notation

时间:2012-07-29 19:46:27

标签: objective-c ios nsnumberformatter nsdecimalnumber

我与NSNumberFormatter发生了严重的争执,即使经过广泛的文档记录,我也无法完全解决我遇到的一个非常简单的问题。我希望你们能帮助我。

我拥有:NSDecimalNumber表示计算结果,显示在UITextField中 我需要的是:该结果的科学记数法。

我在做什么:

-(void)setScientificNotationForTextField:(UITextField*)tf Text:(NSString*)text {

NSString* textBefore = text;

// use scientific notation, i.e. NSNumberFormatterScientificStyle
NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
//[formatter setGeneratesDecimalNumbers:YES];
[formatter setNumberStyle:NSNumberFormatterScientificStyle];
NSDecimalNumber* number = (NSDecimalNumber*)[formatter numberFromString:text];
tf.text = [number descriptionWithLocale:[[Utilities sharedUtilities] USLocale]];

NSString* textAfter = tf.text;
// DEBUG
NSLog(@"setScientificNotation | text before = %@, text after = %@", textBefore, textAfter);

[formatter release];
}

会发生什么:
某个结果可能是0.0099。 textBefore将保持正确的价值。如果我不告诉格式化程序生成十进制数(在上面的代码片段中注释掉),它将从NSDecimalNumber创建一个NSNumber,它会创建一个错误的结果并将textAfter变成0.009900000000000001 - 一个舍入错误到期与NSDecimalNumber相比NSNumber的精度降低。
如果我告诉NumberFormatter生成小数,它仍然会创建错误的结果。更重要的是,在它插入指数表示法之前(例如" 1.23456e-10"),它现在会生成(并因此显示)完整的十进制数,这不是我的意思想。
同样,我希望格式化程序使用NSDecimalNumber,这样它就不会伪造结果,并在必要时使用指数表示法。


我使用的课错了吗?我误解了文档吗?有人可以解释为什么会发生这种情况以及如何创建我想要的行为?如果我找到任何东西,我当然会继续研究和更新。

1 个答案:

答案 0 :(得分:4)

您不能只将NSNumber投射到NSDecimalNumber并期望它能够正常运行。如果您的号码不是太复杂,您可以放弃NSNumberFormatter并尝试使用此号码:

NSDecimalNumber* number = [NSDecimalNumber decimalNumberWithString:text];

这将为您提供一个具有精确度的实际NSDecimalNumber实例。

不幸的是,setGeneratesDecimalNumbers:无效。这是一个known bug。 如果您的号码太复杂而无法与decimalNumberWithString:一起使用,那么您可能会对Apple的API不满意。您唯一的选择是手动将字符串解析为NSDecimalNumber可以理解的内容,或者对NSNumberFormatter给您的不精确值进行一些后处理。

最后,如果你真的想要一个科学记数字,为什么不使用你刚刚使用的数字格式器?只需致电stringFromNumber:即可获取格式化值。