我遇到存储在核心数据中的十进制数问题。当我将数字0.6789保存到数据库时,它保存为0.6788999999999999。
我在某处读过,建议将十进制数列作为十进制来保持精度,因为核心数据会自动处理核心数据中十进制列的NSDecimalNumber。
以下是我的实体类:
@interface TestEntity : NSManagedObject
@property (nonatomic, retain) NSDecimalNumber * cost;
@end
@implementation TestEntity
@dynamic cost;
@end
这就是我插入数据的方式:
TestEntity *envelope = [NSEntityDescription insertNewObjectForEntityForName:@"TestEntity" inManagedObjectContext:self.managedObjectContext];
envelope.cost = [NSDecimalNumber decimalNumberWithString:@"0.6789"];
[self.managedObjectContext save:nil];
请有人帮助我,如何在插入数据库时处理十进制数及其精度?
答案 0 :(得分:3)
核心数据由SQLite支持。根据{{3}},SQLite仅支持最大SQLite documentation的整数和64 bit格式的浮点数(目标C中的double
)。因此精度仅限于这些类型,整数约为18.75个有效数字,浮点数约为15.75个数字。
通常double
或int64_t
适用于大多数应用程序,但需要超过15-18位有效数字的应用程序除外。在某些司法管辖区,银行机构必须依法存储高精度的十进制数字,并为此使用特殊类型。
如果您的申请是标准的,我会使用int64_t
或double
。如果使用NSDecimalNumber
,它将由SQLite引擎存储为64位类型(浮点或整数,取决于是否存在小数部分)。这意味着您的精确度将限制在15-18位。
如果由于其高精度算术而要使用NSDecimalNumber
,则仍然会限制为15/18位数,但如果64bit IEEE 754可以表示为a,则不会引入舍入误差15/18位数字(小数部分或无分数)。
如果您的动态范围较大,NSDecimalNumber
会提供38位数字。为了将其存储在Core Data SQLite支持的持久存储中并且能够维护38位数,您应该将其转换为字符串,来回,以便它作为字符串存储在Core Data中。您可以在NSManagedObject
的子类上创建一个类别,使用几种方法来存储(编码)并将数字检索(解码)为字符串。模型中的基础属性应该是字符串,而不是数字。
NSDecimalNumber
有两种方法-stringValue
和-initWithString:
为您进行转化。您只需构建两个依赖于自定义类别的方法。
总结:
double
获取15位有效数字int64_t
获取18位有效数字NSDecimalNumber
获取38位有效数字(转换为字符串以便存储在CoreData中)答案 1 :(得分:1)
作为CoreData后端的SQLite不支持小数,而是使用float。
来自SQLite文档:
SQLite 3数据库中的每个列都分配了以下之一 类型亲和力:TEXT NUMERIC INTEGER REAL BLOB
更多细节见SQLite文档https://sqlite.org/datatype3.html 3.1.1。亲和力名称示例。