【问题标题】:iPhone Currency input using NSDecimal instead of floatiPhone货币输入使用NSDecimal而不是float
【发布时间】:2011-09-27 00:51:24
【问题描述】:

iPhone/Objective-C/Cocoa 新手在这里。根据 stackoverflow 上的一些帖子,我拼凑了一个 IBAction,我在我正在构建的基本 iPhone 计算器应用程序中使用它。 IBAction 与数字键盘配合使用,无需输入小数点即可输入十进制数字。

我非常努力地坚持“在处理货币时使用 NSDecimal”的格言,尽管我发现像许多其他发布问题的人一样很难做到这一点。我正在稳步前进,但是在我了解 NSDecimal 和 Format Specifications 之后,我确信这会看起来微不足道。

这是我正在使用的 IBAction(它由 Editing Changed UITextField 事件触发):

// called when user touches a key or button
- (IBAction)processKeystrokes:(id)sender
{
 static BOOL toggle = YES; // was this method triggered by the user?

 // the user touched the keypad
 if (toggle)
 {
  toggle = NO;

  // retrieve the strings in input fields
  NSString *currencyField1Text = currencyField1.text;
  NSString *currencyField2Text = currencyField2.text;

  if (sender == currencyField1) {
   currencyField1Text = [currencyField1Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   float currency = [currencyFieldText floatValue]/100; 
   currencyField1.text = [@"" stringByAppendingFormat:@"%0.2f", currency];
  }
  else if (sender == currencyField2) {
   currencyField2Text = [currencyField2Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   NSDecimalNumber *currency2 = [[NSDecimalNumber decimalNumberWithString:currencyField2Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]]; 
   currencyField2.text = [@"" stringByAppendingFormat:@"%@", currency2];
  }
  else  {
   NSLog(@"Some unexpected input");   
  }  
 }
 else 
 {
  toggle = YES;
 }

} // end method calculateResults

currencyField1 代码段使用浮点数,currencyField2 段使用 NSDecimal。

currencyField1 段按需要工作:显示所有小数点后两位数字(即使使用删除键删除所有输入的数字);但是,它会遇到并完美地说明了在处理大货币值时使用浮点数的问题:当输入的数字超过 8 位时,会出现舍入错误。

currencyField2 段通过使用 NSDecimal 代替 float 来避免舍入错误问题;但是,它并不总是显示小数点后两位数的数字——这在使用删除键删除所有输入的数字时显示。我相信问题是由于这行代码:

currencyField2.text = [@"" stringByAppendingFormat:@"%@", currency2];

这是产生所需浮点格式的以下行的推论:

currencyField1.text = [@"" stringByAppendingFormat:@"%0.2f", currency];

所以,我认为我需要等效于 @"%0.2f" 来格式化“0”值 NSDecimalNumber 的显示。我已经在这个问题上待了这么多小时,以至于我很尴尬,但我就是想不通。

感谢任何帮助或指针。

编辑:我合并了 NSNumberFormatter 对象(类似于 Brad 在他的评论中描述的),这似乎已经解决了这个问题。但是,我想要一些关于重构代码的反馈,因为我已经让它工作了。这是修改后的代码:

// called when user touches a key or button
- (IBAction)processKeystrokes:(id)sender
{
 static BOOL toggle = YES; // was this method triggered by the user?

 // the user touched the keypad
 if (toggle)
 {
  toggle = NO;

  // retrieve the strings in input fields
  NSString *currencyField1Text = currencyField1.text;
  NSString *currencyField2Text = currencyField2.text;

  // new code elements
  NSNumberFormatter * nf = [[[NSNumberFormatter alloc] init]autorelease];
  [nf setNumberStyle:NSNumberFormatterCurrencyStyle];
  [nf setCurrencySymbol:@""];
  [nf setCurrencyGroupingSeparator:@""];

  if (sender == currencyField1) {
   currencyField1Text = [currencyField1Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   NSDecimalNumber *currency = [[NSDecimalNumber decimalNumberWithString:currencyField1Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]]; 
   currencyField1.text = [nf stringFromNumber:currency];  
  }
  else if (sender == currencyField2) {
   currencyField2Text = [currencyField2Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   NSDecimalNumber *currency2 = [[NSDecimalNumber decimalNumberWithString:currencyField2Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]]; 
   currencyField2.text = [nf stringFromNumber:currency2];
  }
  else  {
   NSLog(@"Some unexpected input");   
  }  
 }
 else 
 {
  toggle = YES;
 }

} // end method calculateResults

它解决了我最初的问题,但我会很感激任何关于如何改进它的建议。谢谢。

【问题讨论】:

    标签: iphone cocoa-touch keyboard decimal nsdecimalnumber


    【解决方案1】:

    如果您想保证文本值的小数点后有 2 位数字,您可以使用如下代码中的 NSNumberFormatter(取自答案 here):

    NSNumberFormatter *decimalNumberFormatter = [[NSNumberFormatter alloc] init];
    [decimalNumberFormatter setMinimumFractionDigits:2];
    [decimalNumberFormatter setMaximumFractionDigits:2];
    currencyField2.text = [decimalNumberFormatter stringFromNumber:currency2];
    [decimalNumberFormatter release];
    

    我相信这应该保持 NSDecimalNumber 的精度。就个人而言,出于性能原因,我更喜欢使用 NSDecimal C 结构,但这有点难以将值输入和输出。

    【讨论】:

    • 谢谢布拉德。您的建议有效,但如果用户删除所有输入的数字,前导“0”会丢失。这将导致显示值“.00”,而我想要“0.00”。我用“[nf setNumberStyle:NSNumberFormatterCurrencyStyle];”解决了这个问题它带来了小数点和两个尾随数字;还有我使用 "[nf setCurrencySymbol:@""];" 消除的货币符号 ("$") 和货币组分隔符 (",")和 "[nf setCurrencyGroupingSeparator:@""];"分别。感谢您的指点——NSNumberFormatter 解决了这个问题!
    【解决方案2】:

    你不能使用-setFormat: 方法(NSNumberFormatter)代替NSNumberFormatter 吗?似乎应该能够根据您的目的对其进行配置,并且您不必处理货币格式字符串上的奇怪“黑客”。

    更多信息见:

    【讨论】:

      猜你喜欢
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多