Swift高精度数据类型Decimal
Swift高精度数据类型Decimal

Swift高精度数据类型Decimal

Decimal 是 Swift 中用于表示高精度、十进制数值的类型,适用于对精度要求较高的场景,比如财务计算、货币处理、科学运算等。它在底层使用十进制浮点数表示,因此比二进制浮点数(如 Float 或 Double)能更准确地表示和操作十进制数。

Decimal 是 Swift 的类型,但它的实现来源于 Foundation 框架。

主要特点

1、高精度

使用十进制浮点数存储,避免了二进制浮点数表示十进制数时的舍入误差。

适合货币、财务计算等需要精确小数位的应用场景。

2、支持范围广

可以表示非常大的或非常小的数字,同时保持高精度。

3、不可变性

Decimal 本质上是不可变的,每次修改都会返回一个新的实例。

4、与 NSDecimalNumber 的兼容

Decimal 是 NSDecimalNumber 的 Swift 类型化替代。

创建 Decimal

1、使用直接赋值

可以直接通过十进制浮点数或字符串来创建:

let decimal1: Decimal = 123.456
let decimal2 = Decimal(123.456)
let decimal3 = Decimal(string: "123.456")!

2、使用整数、浮点数创建

let intDecimal = Decimal(123)       // 从整数
let doubleDecimal = Decimal(123.45) // 从双精度浮点数

3、使用字符串创建(适合处理更大数值)

if let largeDecimal = Decimal(string: "12345678901234567890.12345") {
    print(largeDecimal) // 12345678901234567890.12345
}

基本操作

Decimal 支持常见的算术操作和比较操作,类似于其他数值类型。

1、算术运算

let value1: Decimal = 10.5
let value2: Decimal = 3.2

let sum = value1 + value2         // 加法
let difference = value1 - value2  // 减法
let product = value1 * value2     // 乘法
let quotient = value1 / value2    // 除法

2、比较操作

Decimal 支持常规的比较运算符:

let decimal1: Decimal = 5.0
let decimal2: Decimal = 7.0

print(decimal1 < decimal2) // true
print(decimal1 == decimal2) // false

3、提取值

可以将 Decimal 转换为其他数值类型:

let decimalValue: Decimal = 123.456

let doubleValue = Double(truncating: decimalValue as NSNumber)
let intValue = Int(truncating: decimalValue as NSNumber)
print(doubleValue) // 123.456
print(intValue)    // 123

Double(truncating:) 和 Int(truncating:) 是 Swift 中用于将一个支持数值类型的对象(如 NSNumber)转换为目标数值类型的方法。它们主要用于处理跨类型数值转换,尤其是 Foundation 框架中的类型,比如 NSNumber。

精度与舍入

设置小数位数

Decimal 提供了非常灵活的舍入方式和精度控制,通过 NSDecimalRound() 函数可以实现:

var number: Decimal = 123.456789
var roundedNumber = Decimal()
NSDecimalRound(&roundedNumber, &number, 2, .plain) // 四舍五入到小数点后两位
print(roundedNumber) // 输出 123.46

适用场景

1、货币与财务计算

Decimal 能精确表示和处理货币数值,避免因二进制浮点数导致的舍入误差。

let price: Decimal = 19.99
let quantity: Decimal = 3
let total = price * quantity // 59.97,无精度问题

2、大数值或高精度计算

可表示非常大的数字或处理需要高精度的小数。

let largeValue = Decimal(string: "12345678901234567890.123456789")!
print(largeValue) // 输出 12345678901234567890.123456789

3、科学计算

使用高精度的计算场景中,Decimal 能提供更准确的结果。

总结

Decimal 是一个强大的工具,用于处理高精度数值和避免浮点舍入误差,特别是在财务、科学计算等场景下非常有用。它结合了十进制浮点数的准确性和 Swift 的类型安全,为开发者提供了一种灵活而可靠的解决方案。

扩展知识

十进制浮点数与二进制浮点数的区别

1、定义

十进制浮点数

数值以 10 为基数存储,类似于我们日常使用的十进制数系统。适合处理精确表示十进制小数的场景,如货币和财务计算。

二进制浮点数

数值以 2 为基数存储,常见于计算机中的 Float 和 Double 类型。更适合科学计算和对精度要求不严格的通用数值运算。

2、精确度

十进制浮点数

可以精确地表示十进制小数。

比如 0.1 用十进制浮点数表示时可以完全存储为 0.1。

二进制浮点数

某些十进制小数无法精确表示,存储时会出现舍入误差。

比如 0.1 在二进制浮点数中会存储为一个近似值:0.10000000000000000555…。

3、应用场景

十进制浮点数

财务计算(例如货币金额)。

精确小数表示(如计量数据、百分比)。

二进制浮点数

科学计算(对性能需求高,误差容忍度较大)。

大范围数值的快速计算。

4、性能

十进制浮点数

运算性能通常较低,因为它不是计算机原生的数值表示。

需要更多计算来模拟十进制操作。

二进制浮点数

由于是计算机硬件原生支持的数值表示,运算性能更高。

Decimal 的范围

Swift 的 Decimal 类型基于 Foundation 框架中的 NSDecimal,使用十进制浮点数实现,其范围和精度如下:

数值范围

最小值:±1e-38(0.000…0001,有 38 个 0)。

最大值:±1e+38(10 的 38 次方)。

精度

最大支持 38 位有效数字。

选择十进制还是二进制浮点数

优先使用 Decimal 的场景

1、财务应用,如货币运算。

2、需要精确表示十进制小数的场景。

3、不希望因二进制误差影响结果的应用。

优先使用 Double 或 Float 的场景

1、科学计算或高性能需求。

2、对误差容忍度较高的应用。

3、需要表示非常大范围的数值。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注