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 が 32 ビットではなく 64 ビットになったためです。フォーマッタによって返される値は1.844674407370955e+19、 uint64_t ではなくdouble になりまし18446744073709551615た。

すべての int64 および unsigned int64 に対して正確に成功する組み込みメソッドはありますか、それとも自分で実装する必要がありますか?

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

考慮すべきもう 1 つの点は次のとおりです。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 に答える