核心数据和 NSDecimalNumber
Coredata and NSDecimalNumber
我对存储在核心数据中的小数有疑问。当我将数字 0.6789 保存到数据库中时,它被保存为 0.6788999999999999。
我在某处读到,建议将小数列设置为小数以保持精度,因为核心数据会自动处理核心数据中小数列的 NSDecimalNumber。
下面是我的实体class:
@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];
请大神帮帮我,插入数据库时应该如何处理十进制数及其精度?
作为 CoreData 后端的 SQLite 不支持小数,而是使用浮点数。
来自 SQLite 文档:
Each column in an SQLite 3 database is assigned one of the following
type affinities: TEXT NUMERIC INTEGER REAL BLOB
更多详细信息请参阅 SQLite 文档 https://sqlite.org/datatype3.html 3.1.1。亲缘关系名称示例。
核心数据由 SQLite 支持。根据 SQLite documentation SQLite only supports integers up to 64 bit and floating point numbers with the 64bit IEEE 754 格式(Objective C 中的 double
)。所以精度仅限于这些类型,整数约为18.75位有效数字,浮点数约为15.75位。
通常 double
或 int64_t
适用于大多数应用程序,但需要超过 15-18 位有效数字的精度除外。在某些司法管辖区,银行机构必须依法存储高精度的十进制数,为此他们使用特殊类型。
如果您的应用程序是标准的,我会使用 int64_t
或 double
。如果你使用 NSDecimalNumber
它将被 SQLite 引擎存储为 64 位类型(浮点数或整数取决于小数部分的存在)。这意味着您的精度将限制在 15-18 位数字。
如果你想使用NSDecimalNumber
因为它的高精度算法,你仍然会被限制在15/18位,但如果你的dynamic range可以表达,就不会引入舍入误差作为 15/18 位数字(带或不带小数部分)。
如果您的动态范围更大,NSDecimalNumber
提供 38 位数字。为了将它存储在 Core Data SQLite 支持的持久存储中并能够保持 38 位数字,您应该将它来回转换为字符串,以便它作为字符串存储在 Core Data 中。您可以在 NSManagedObject
的子类上创建一个类别,并使用几种方法将数字存储(编码)和检索(解码)为字符串。模型中的基础 属性 应该是字符串,而不是数字。
NSDecimalNumber
有两种方法 -stringValue
和 -initWithString:
可以为您进行转换。您只需要在您的自定义类别中构造两个依赖于这些的方法。
总结:
- 如果需要小数,请使用
double
表示 15 位有效数字
- 如果您不需要小数,请使用
int64_t
表示 18 位有效数字
- 如果需要精度高的十进制数,38位有效数字使用
NSDecimalNumber
(需要转换成字符串存入CoreData)
我对存储在核心数据中的小数有疑问。当我将数字 0.6789 保存到数据库中时,它被保存为 0.6788999999999999。
我在某处读到,建议将小数列设置为小数以保持精度,因为核心数据会自动处理核心数据中小数列的 NSDecimalNumber。
下面是我的实体class:
@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];
请大神帮帮我,插入数据库时应该如何处理十进制数及其精度?
作为 CoreData 后端的 SQLite 不支持小数,而是使用浮点数。
来自 SQLite 文档:
Each column in an SQLite 3 database is assigned one of the following type affinities: TEXT NUMERIC INTEGER REAL BLOB
更多详细信息请参阅 SQLite 文档 https://sqlite.org/datatype3.html 3.1.1。亲缘关系名称示例。
核心数据由 SQLite 支持。根据 SQLite documentation SQLite only supports integers up to 64 bit and floating point numbers with the 64bit IEEE 754 格式(Objective C 中的 double
)。所以精度仅限于这些类型,整数约为18.75位有效数字,浮点数约为15.75位。
通常 double
或 int64_t
适用于大多数应用程序,但需要超过 15-18 位有效数字的精度除外。在某些司法管辖区,银行机构必须依法存储高精度的十进制数,为此他们使用特殊类型。
如果您的应用程序是标准的,我会使用 int64_t
或 double
。如果你使用 NSDecimalNumber
它将被 SQLite 引擎存储为 64 位类型(浮点数或整数取决于小数部分的存在)。这意味着您的精度将限制在 15-18 位数字。
如果你想使用NSDecimalNumber
因为它的高精度算法,你仍然会被限制在15/18位,但如果你的dynamic range可以表达,就不会引入舍入误差作为 15/18 位数字(带或不带小数部分)。
如果您的动态范围更大,NSDecimalNumber
提供 38 位数字。为了将它存储在 Core Data SQLite 支持的持久存储中并能够保持 38 位数字,您应该将它来回转换为字符串,以便它作为字符串存储在 Core Data 中。您可以在 NSManagedObject
的子类上创建一个类别,并使用几种方法将数字存储(编码)和检索(解码)为字符串。模型中的基础 属性 应该是字符串,而不是数字。
NSDecimalNumber
有两种方法 -stringValue
和 -initWithString:
可以为您进行转换。您只需要在您的自定义类别中构造两个依赖于这些的方法。
总结:
- 如果需要小数,请使用
double
表示 15 位有效数字 - 如果您不需要小数,请使用
int64_t
表示 18 位有效数字 - 如果需要精度高的十进制数,38位有效数字使用
NSDecimalNumber
(需要转换成字符串存入CoreData)