2

我正在接收和解析 JSON 并将数据存储到 Core Data 中。一些数据是存储为 NSDecimalNumber 的货币,但其中一些值的精度高于两位小数。

例如,如果我从服务中获得一个值,例如 8.2399999995,我想将它作为 8.24 存储在 Core Data 中。有没有办法将我的模型设置为小数点后两位的精度?或者我是否需要在存储后手动舍入每个值?

更新

Leijonien 感谢您提供的信息。我尝试这样做,但在保存格式化值时遇到了一些麻烦。我检查了 JSON 并搜索了谷歌,结果发现我从服务中得到了一个干净的价值。RESTKit 是问题.... https://github.com/RestKit/RestKit/issues/1405

但是,我在我的一个 NSManagedObject 类上创建了一个类别,覆盖了我想要的属性的设置器,格式化了值,但我仍然在我的数据库中看到长十进制值。这是我的代码。

- (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

2

CoreData 只会存储您传递的值,因此如果您只需要 2 位数字,您应该自己四舍五入该值。在存储之前可能会更好地舍入该值,因此您只需对每个结果执行一次。

于 2013-11-13T15:41:13.833 回答
1

需要注意的一件事是,某些(大多数?)十进制数不能以与我们认为的完全相同的方式存储在浮点二进制中。那里有很多要读的东西,但我喜欢这个的详细方法:http ://www.cprogramming.com/tutorial/floating_point/understanding_floating_point_representation.html 。

因此,对于您的数字,.24不能用浮点数表示,因为二进制只能给出数字的小数部分由.5、.25、.125、...组成(这可能是缺少一些特殊规则,但这是一般的想法)。因此,为了表示.24,它使用尽可能多的较低值来尽可能接近。

NSDecimalNumber 被设置为舍入它,但如果你不告诉它舍入任何东西,你也会看到相同的8.23999...值。

于 2015-01-30T16:19:35.187 回答
1

事实证明,问题不在于 RESTKit。事实上,问题似乎出在 Core Data 上。这就是为什么在我的 setter 方法中打印到控制台打印了格式正确的数字,但数字在 db 中的精度错误。对于这种情况,最好的补救措施是在从 Core Data 中提取数字之后,重写 getter 方法并格式化那里的数字。以下似乎有效......如果您发现其他任何有效的方法,请告诉我。

- (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 回答