Swift 中基础的数据类型跟 C语言
和 OC
中也比较相似.
整形(int)
整形
就是我们正常认知中的 整数
, 比如 42
和 -23
. 他不包含 小数
部分. 整数 包括 有符号
的 正数
和负数
, 也包括 无符号
的 0
.
Swift 中提供了 8, 16, 32 和 64 位的 带符号
和 无符号
的整数. 这些整数遵循类似 C语言 的命名约定:
| Bit | 无符号 | 有符号 |
| —- | —— | —— |
| 8 | UInt8 | Int8 |
| 16 | UInt16 | Int16 |
| 32 | UInt32 | Int32 |
| 64 | UInt64 | Int64 |
整形数字范围
可以通过 Int
的 min
和 max
属性读取 最小值
和 最大值
.
1
2
let minValue = UInt8.min // minValue = 0
let maxValue = UInt8.max // maxValue = 255
Int
一般情况下, 我们无需选择特定 bit
的数字类型. Swift 提供了一个数据类型 Int
, 它的大小跟系统有关.
- 在 32 位系统中,
UInt
相当于UInt32
. - 在 64 位系统中,
UInt
相当于UInt64
.
注意 只有在有特别的需求, 需要使用与平台字大小的无符号整形数字的时候, 才使用
UInt
. 否则, 推荐使用Int
, 即使你已经确定存储的数据是 非负数. 使用统一的Int
类型可以避免在不同数字类型之间进行转换的情况.
浮点数
浮点数 就是一个 带小数部分
的数字. 比如: 3.1415926
, -2.7
.
浮点类型 值的范围比 整形 大的多. 并且可以存储比 整形 数 大的多
或 小得多
的数.
Swift 提供了 2 种浮点类型:
- Double 表示一个
64位
的浮点数. - Float 表示一个
32位
的浮点数.
注意 Double 的精度至少为
15位
小数, Float 的精度低至6位
小数. 在开发中使用哪个类型取决于需求的数字的范围
和精度
. 当 2 种类型都合适的情况下, Double 是首选.
类型安全和类型推断
Swift 是一种 类型安全
的编程语言. 如果一个需要 String
类型作为参数的代码段就不能传入 Int
类型的参数.
Swift 是类型安全的, 因此在代码编译阶段会执行类型检查. 如果代码中有类型不匹配就会报 编译错误
. 这也可以帮助我们在开发过程中尽早发现错误.
当我们在处理不同类型的值的时候, 类型检查 可以帮助我们避免错误. 当然, 也不是说所有的 常量 和 变量 都必须指定声明其具体类型. 如果我们没有指定数据类型, Swift 就会使用 类型推断 来确定适合的类型. 类型推断 可以使编译器在编译阶段通过检查 常量/变量
的 值
来推断其 类型
.
如果你给一个新的 常量 赋值为 42
而未声明其类型, 类型推断 就会推断出这个常量为 Int
类型:
1
2
let meaningOfLife = 42
// meaningOfLife 被推断为 Int 类型
同样的, 如果你没有为 浮点型
常量声明其具体类型, 类型推断 会推断其为 Double
类型:
1
2
let pi = 3.14159
// pi 被推断为 Double 类型
如果一个表达式中包含了 整数
和 浮点数
, 则会从上下文来推断其为 Double
类型:
1
2
let anotherPi = 3 + 0.14159
// anotherPi 也会被推断为 Double 类型
数字字面值
一个 整形 数字可以被写成一下几种形式: | 进制 | 前缀 | | ——– | —— | | 十进制 | 无前缀 | | 二进制 | 0b | | 八进制 | 0o | | 十六进制 | 0x |
以下几种写法都代表了数字 17
:
1
2
3
4
let decimalInteger = 17 // 十进制
let binaryInteger = 0b10001 // 二进制
let octalInteger = 0o21 // 八进制
let hexadecimalInteger = 0x11 // 十六进制
浮点型 数字可以被表示为 十进制(无前缀)
和 十六进制(0x前缀)
. 浮点型 必须在 小数点
两侧都有 1 个数字 (或者十六进制数字).
十进制
浮点数可以有一个可选的指数
, 由大写或者小写的e
表示.十六进制
浮点数必须有一个指数, 用大写或小写的p
表示.
十进制
的以 exp
为指数的浮点数, 底数
* 10^exp
.
1.25e2
等同于1.25 * 10^2
或者125.0
.1.25e-2
等同于1.25 * 10^-2
或者0.0125
.
十六进制
的以 exp
为指数的浮点数, 底数
* 2^exp
.
0xFp2
等同于15 * 2^2
或者60.0
.0xFp-2
等同于15 * 2^-2
或者3.75
.
以下几种写法的值都为 12.1857
:
1
2
3
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
数字还可以加入额外的 "_"
或者 "0"
来提高其可读性, 并且其值不会受到影响:
1
2
3
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
数字类型转换
在开发中, 尽管已知 常量 或者 变量 存储的是无符号的数字, 也应该尽量使用 Int
类型. 使用默认的 Int
类型就可以在代码中直接做运算.仅仅在特殊需求的情况下选择其他的 整数类型.
整形转换
不同 数值类型
的 常量/变量
所能存储的数值范围是不同的. 一个 Int8
的 常量/变量
可以能存储的数值范围为 -128 ~ 127
. 然而, 一个 UInt8
类型的 常量/变量
能够存储数值的范围为 0 ~ 255
. 当你尝试把一个超出存储范围的数字存储进 常量/变量
的时候, 代码编译就会报错:
1
2
3
4
5
let cannotBeNegative: UInt8 = -1
// UInt8 不能存储负数, 因此此处会报错
let tooBig: Int8 = Int8.max + 1
// Int8 不能存储一个大于 Int8 最大值的数值, 此处也会报错
因为每种 数值类型 可以存储的数值范围都不想同, 因此必须根据不同情况来选择合适的 数值类型. 这样可以防止隐式转换错误. 且有助于在代码中明确类型转换的意图.
可以通过使用现有 数值
作为目标类型的初始值来初始化一个新的 常量/变量
达到从一个数值类型转换为另一个数值类型的目的. 在下面的事例中, 常量 twoThousand
为 UInt16
, 另一个 常量 one
是 UInt8
. 因为他们的 类型不同, 因此无法直接进行 加法运算. 所以在此案例中调用 UInt16(one)
, 使用 one
的值作为初始值创建一个新得 UInt16
类型的数值, 然后对其和 twoThousand
做运算:
1
2
3
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
因为 +
两侧现在都是 UInt16
类型, 因此加法运算是可以进行的. 因为此处是 2 个 UInt16
类型进行运算, 所以运算结果也被推断为 UInt16
类型.
整形和浮点型转换
整形 和 浮点型 之间的转换必须是显式转换.
1
2
3
4
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi = 3.14159, 被推断为 Double 类型
案例中 常量 three
的值用于创建了一个 Double
类型的值, 此时 +
两边值的类型均为 Double
所以运算是被允许的.
浮点型 转换为 整形 同样的也必须是 显式转换. 整形 可以使用 Double
或 Float
来初始化.
1
2
let integerPi = Int(pi)
// integerPi 等于 3, 并且被推断为 Int 类型
当 浮点型 被用于初始化为 整形 的时候就会被 截断. 比如: 4.75
会被截断为 4
. -3.9
被截断为 -3
.
类型别名
类型别名 是现有类型定义的 替代名称. 定义 类型别名 使用 typealias
关键字.
当你希望使用上下文更加合适的名称来引用现有类型时, 类型别名 将会非常有用.
1
typealias AudioSample = UInt16
定义了 类型别名 之后, 就可以在任何可能使用 原始名称 的地方使用 别名.
1
2
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound 等于 0
此处 AudioSample
是为 UInt16
定义的别名, 因此 AudioSample.min
等价于 UInt16.min
, 所以 maxAmplitudeFound
的值为 0
.
布尔类型
Swift 有一个基本布尔类型 Bool
. 布尔值被成为 逻辑值
, 因为他们只能是 真
或 假
. Swift 提供了 2 个布尔常量值 true
和 false
.
1
2
let orangesAreOrange = true
let turnipsAreDelicious = false
此处因为 orangesAreOrange
和 turnipsAreDelicious
使用 布尔值
初始化, 因此被推断为 布尔类型.
如果你使用 true
或 false
初始化了 常量/变量
, 就无需声明其类型为 Bool
. 当使用已知类型的值初始化 常量/变量
时候, 类型推断有助于使代码更加简介和易读.
布尔值在处理条件语句时候特别有用, 例如 if
语句:
1
2
3
4
5
6
if turnipsAreDelicious {
print("Mmm, tasty turnips!")
} else {
print("Eww, turnips are horrible.")
}
// 打印结果: "Eww, turnips are horrible."
Swift 的 类型安全 可以防止 非布尔值
替换 Bool
类型的情况. 下面的例子就会报错:
1
2
3
4
let i = 1
if i {
// 此处会报编译错误.
}
但是下面的例子是可以的:
1
2
3
4
let i = 1
if i == 1 {
// 可以编译通过
}
比较语句 i == 1
结果的类型为 Bool
, 因此第二个例子可以正常编译通过.
与其他 类型安全 事例一样, 这种方法避免了意外的错误, 并确保特定代码段的意图始终清晰.