2

JSON を受信して​​解析し、データを Core Data に保存しています。一部のデータは NSDecimalNumber として格納されている通貨ですが、これらの値の一部は小数点以下 2 桁よりも高い精度を持っています。

たとえば、サービスから 8.2399999995 などの値を取得した場合、これを Core Data に 8.24 として保存します。モデルを小数点以下 2 桁の精度に設定する方法はありますか? または、保存後に各値を手動で丸める必要がありますか?

アップデート

Leijonien さん、情報ありがとうございます。私はそれをやろうとしましたが、フォーマットされた値を保存するのに問題があります。JSON をチェックして Google を検索したところ、サービスからクリーンな値を取得していることがわかりました。RESTKit が問題です.... https://github.com/RestKit/RestKit/issues/1405 .

ただし、NSManagedObject クラスの 1 つでカテゴリを作成し、必要な属性のセッターをオーバーライドし、値をフォーマットしましたが、DB に長い 10 進値が表示されます。これが私のコードです。

- (void)setAmount:(NSDecimalNumber *)amount {
    NSDecimalNumberHandler *round = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                                                                           scale:2
                                                                                raiseOnExactness:NO
                                                                                 raiseOnOverflow:NO
                                                                                raiseOnUnderflow:NO
                                                                             raiseOnDivideByZero:YES];
    NSDecimalNumber *newAmount = [amount decimalNumberByRoundingAccordingToBehavior:round];
    NSLog(@"%@", newAmount);
    [self setPrimitiveValue:newAmount forKey:@"amount"];
}

奇妙なことnewAmountに、コンソールに出力すると、希望どおりに 8.24 の形式になりますが、データベースを確認すると、8.2399999995 として保存されます。ここで何か間違ったことをしていますか?

4

3 に答える 3

1

注意すべきことの 1 つは、一部の (ほとんどの?) 10 進数は、私たちが考えるのとまったく同じ方法で浮動小数点 2 進数に格納できないことです。そこには読むべきものがたくさんありますが、私はこれの詳細なアプローチが好きです: http://www.cprogramming.com/tutorial/floating_point/understanding_floating_point_representation.html .

したがって、あなたの数値では、.24を浮動小数点で表現することはできません。2 進法では、数値の小数部分が.5、.25、.125、... で構成されていることしか得られないためです(つまり、いくつかの特別なルールがありませんが、それが一般的な考え方です)。したがって、.24を表すために、できるだけ多くの低い値を使用してできるだけ近づけます。

NSDecimalNumber はそれを丸めるように設定されていますが、何かを丸めるように指示しないと、同じ8.23999...の値がそこにも表示されます。

于 2015-01-30T16:19:35.187 に答える
1

結局のところ、問題は RESTKit ではありません。実際、問題は Core Data にあるようです。これが、setter メソッドでコンソールに出力すると正しい形式の数値が出力されたのに、db では数値の精度が間違っている理由です。この状況の最善の解決策は、ゲッター メソッドをオーバーライドし、Core Data から数値を取得した後で数値をフォーマットすることでした。以下は機能しているようです...他に機能するものが見つかった場合はお知らせください。

- (NSDecimalNumber*)amount {
    [self willAccessValueForKey:@"amount"];
    NSDecimalNumber* unroundedAmount = [self primitiveValueForKey:@"amount"];
    [self didAccessValueForKey:@"amount"];

    NSDecimalNumberHandler *round = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                                                                           scale:2
                                                                                raiseOnExactness:NO
                                                                                 raiseOnOverflow:NO
                                                                                raiseOnUnderflow:NO
                                                                             raiseOnDivideByZero:YES];
    NSDecimalNumber *roundedAmount = [unroundedAmount decimalNumberByRoundingAccordingToBehavior:round];

    return roundedAmount;
}
于 2013-12-05T02:43:57.103 に答える