为什么将Double转换为Int不会在Swift中返回可选的Int?

时间:2016-06-21 23:32:23

标签: swift string int

将String转换为Int会返回一个可选值,但将Double转换为Int不会返回可选值。这是为什么?我想检查double值是否大于最大Int值,但因为转换函数没有返回可选值,我无法使用可选绑定进行检查。

var stringNumber: String = "555"
var intValue = Int(stringNumber) // returns optional(555)

var doubleNumber: Double = 555
var fromDoubleToInt = Int(doubleNumber) // returns 555

因此,如果我尝试转换大于最大整数的双数,则会崩溃而不是返回nil。

var doubleNumber: Double = 55555555555555555555
var fromDoubleToInt = Int(doubleNumber) // Crashes here

我知道还有另一种检查双数是否大于最大整数值的方法,但我很好奇为什么会这样发生。

2 个答案:

答案 0 :(得分:3)

如果我们考虑大多数双倍,转换为Int只是意味着删除小数部分:

let pieInt = Int(3.14159) // 3

然后Int(Double)构造函数返回nil的唯一情况是溢出。

对于字符串,转换为Int会返回一个可选的,因为通常是字符串,例如“Hello world!”不能以一种普遍有意义的方式表示为Int。因此,在字符串不能表示为整数的情况下,我们返回nil。顺便说一下,这包括可以完美表示为双精度或浮点数的值:

考虑:

let iPi = Int("3.14159")
let dPi = Double("3.14159")

在这种情况下,iPinildPi3.14159。为什么?因为"3.14159"没有有效的Int代表。

但与此同时,当我们使用Int构造函数接受Double并返回非可选项时,我们得到一个值。

那么,如果更改了该构造函数以返回一个可选项,为什么它会为3而不是3.14159返回nil3.14159不能表示为整数。

但是如果你想要一个返回可选Int的方法,当nil溢出时返回Double,你就可以编写那个方法了。

extension Double {
    func toInt() -> Int? {
        let minInt = Double(Int.min)
        let maxInt = Double(Int.max)

        guard case minInt ... maxInt = self else {
            return nil
        }

        return Int(self)
    }
}

let a = 3.14159.toInt() // returns 3
let b = 555555555555555555555.5.toInt() // returns nil

答案 1 :(得分:0)

具有可选返回类型的可用初始值设定项和方法适用于程序员无法知道参数值是否会导致失败,或者验证操作是否成功等于执行操作的情况:

let intFromString = Int(someString)
let valueFromDict = dict[someKey]

从字符串中解析整数需要检查字符串中的数字/非数字字符,因此检查与工作相同。同样,检查字典是否存在密钥与查找密钥的值相同。

相比之下,某些操作是程序员需要事先验证您的参数或前提条件符合预期的事情:

let foo = someArray[index]
let bar = UInt32(someUInt64)
let baz: UInt = someUInt - anotherUInt

您可以 - 并且在大多数情况下应该 - 在运行时测试index < someArray.countsomeUInt64 < UInt32.max以及someUInt > anotherUInt。这些假设对于处理这些类型是至关重要的。一方面,你really want to design around them from the start。另一方面,你不希望你做的每一点数学都用可选的解包 - 这就是为什么我们有类型的公理被预先说明的原因。