NSNumberFormatter、NSDecimalNumber 和科学记数法

Posted

技术标签:

【中文标题】NSNumberFormatter、NSDecimalNumber 和科学记数法【英文标题】:NSNumberFormatter, NSDecimalNumber and Scientific Notation 【发布时间】:2012-07-29 19:46:27 【问题描述】:

我与 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 将保持正确的值。如果我不告诉格式化程序生成十进制数(在上面的 sn-p 中注释掉),它将从 NSDecimalNumber 创建一个 NSNumber,这会创建一个错误的结果并将 textAfter 转换为 0.009900000000000001 - 由于NSNumber 在 NSDecimalNumber 上的精度降低。 如果我告诉 NumberFormatter 生成小数,它仍然会产生错误的结果。更重要的是,在它插入指数符号(例如“1.23456e-10”)之前,它现在会生成(并因此显示)完整的十进制数,这不是我想要的。 再次,我想让格式化程序使用 NSDecimalNumber,这样它就不会伪造结果,并且在必要时使用指数表示法。

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

【问题讨论】:

【参考方案1】:

您不能只是将NSNumber 转换为NSDecimalNumber 并期望它能够工作。如果您的号码不是太复杂,您可以放弃NSNumberFormatter 并尝试使用它:

NSDecimalNumber* number = [NSDecimalNumber decimalNumberWithString:text];

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

很遗憾,setGeneratesDecimalNumbers: 无法正常工作。这是known bug。 如果您的号码太复杂而无法使用 decimalNumberWithString:,那么您可能对 Apple 的 API 不走运。您唯一的选择是将字符串手动解析为 NSDecimalNumber 可以理解的内容,或者对 NSNumberFormatter 提供给您的不精确值执行一些后处理。

最后,如果你真的想要一个科学计数法的数字,为什么不直接使用你刚刚使用的数字格式化程序呢?只需调用stringFromNumber: 即可获取格式化值。

【讨论】:

确实(我在查看上述答案的第一个版本后意识到)我应该将 stringFromNumber 与我从文本中获得的 NSDecimalNumber 一起使用,而不是 numberFromString。我现在根据字符串的长度格式化字符串:如果太长而无法放入文本字​​段,我将应用科学记数法。它现在不是 100% 有效,但我认为它正在形成。感谢您的回答和链接;我有点希望它是一个错误^^

以上是关于NSNumberFormatter、NSDecimalNumber 和科学记数法的主要内容,如果未能解决你的问题,请参考以下文章

NSNumberFormatter - 获取货币代码的货币符号

NSNumberFormatter、NSDecimalNumber 和科学记数法

NSNumberFormatter 用于 2 个小数位

使用 NSNumberFormatter 循环中的 Objective C 自动释放

NSNumberFormatter 将浮点字符串格式化为整数

NSNumberformatter 添加额外的零