1

我一直在使用以下方法将 NSString 解析为 NSNumber:

// (a category method on NSString)
-(NSNumber*) tryParseAsNumber {
  NSNumberFormatter* formatter = [NSNumberFormatter new];
  [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
  return [formatter numberFromString:self];
}

我进行了测试以验证它是否正常工作:

test(@"".tryParseAsNumber == nil);
...
test([(@NSUIntegerMax).description.tryParseAsNumber isEqual:@NSUIntegerMax]);
...

当我切换到 iPhone 6 上进行测试时,最大值测试开始失败,可能是因为 NSUInteger 现在是 64 位而不是 32 位。格式化程序返回的值现在是 double1.844674407370955e+19而不是 uint64_t 18446744073709551615

是否有一种内置方法可以完全适用于所有 int64s 和 unsigned int64s,还是我必须自己实现一个?

4

2 回答 2

1
+ [NSNumber numberWithLongLong:]
+ [NSNumber numberWithUnsignedLongLong:]

你试过这些吗?

编辑

我完全不确定你最终会用你的实例做什么NSNumber,但考虑一下这NSDecimalNumber似乎正是你想要的:

NSDecimalNumber *decNum = [NSDecimalNumber decimalNumberWithString:@"18446744073709551615"];
NSLog(@"%@", decNum);

产生:

2014-09-21 15:11:25.472 Test[1138:812724] 18446744073709551615

这是要考虑的另一件事:NSDecimalNumber"is a" NSNumber,因为它是后者的子类。所以看起来,无论你可以用 做什么NSNumber,你都可以用NSDecimalNumber.

于 2014-09-21T21:22:46.053 回答
0

trudyscousin的回答让我弄清楚了。

NSDecimalNumber decimalNumberWithString:能够以全精度解析,但它允许一些错误的输入(例如“88ffhih”被解析为 88)。另一方面,NSNumberFormatter numberFromString:总是检测到错误的输入但会丢失精度。他们有相反的弱点。

所以……两者都做。例如,这是一个应该解析可表示的 NSUIntegers 的方法,但仅此而已:

+(NSNumber*) parseAsNSUIntegerElseNil:(NSString*)decimalText {
    // NSNumberFormatter.numberFromString is good at noticing bad inputs, but loses precision for large values
    // NSDecimalNumber.decimalNumberWithString has perfect precision, but lets bad inputs through sometimes (e.g. "88ffhih" -> 88)
    // We use both to get both accuracy and detection of bad inputs
    NSNumberFormatter* formatter = [NSNumberFormatter new];
    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
    if ([formatter numberFromString:decimalText] == nil) {
        return nil;
    }
    NSNumber* value = [NSDecimalNumber decimalNumberWithString:decimalText];

    // Discard values not representable by NSUInteger
    if (![value isEqual:@(value.unsignedIntegerValue)]) {
        return nil;
    }

    return value;
}
于 2014-10-07T15:22:03.460 回答