03_Swift2基础之基本数据类型+相互转换

时间:2024-01-19 23:06:20

1. 整数

 整数就是没有小数部分的数字,比如`42`和`-23`。整数可以是`有符号`(正、负、零)或者`无符号`(正、零)。

 Swift 提供了,,和位的有符号和无符号整数类型。这些整数类型和 C语言的命名方式很像,比如8位无符号整数类型是`UInt8`,32位有符号整数类型是`Int32`。就像 Swift 的其他类型一样,整数类型采用大写命名法。

 1> 整数范围

  你可以访问不同整数类型的`min`和`max`属性来获取对应类型的最大值和最小值:

  let minValue = UInt8.min  // minValue 为 0,是 UInt8 类型的最小值

     let maxValue = UInt8.max  // maxValue 为 255,是 UInt8 类型的最大值

03_Swift2基础之基本数据类型+相互转换

03_Swift2基础之基本数据类型+相互转换

 2> Int(有符号整型)

  一般来说,你不需要专门指定整数的长度。Swift 提供了一个特殊的整数类型`Int`,长度与当前平台的原生字长相同:

   * 在32位平台上,`Int`和`Int32`长度相同。

   * 在64位平台上,`Int`和`Int64`长度相同。

  除非你需要特定长度的整数,一般来说使用`Int`就够了。这可以提高代码一致性和可复用性。即使是在32位平台上,`Int`可以存储的整数范围也可以达到`-2147483648`~`2147483647`,大多数时候这已经足够大了。

 3>UInt(无符号整型)

  Swift 也提供了一个特殊的无符号类型`UInt`,长度与当前平台的原生字长相同(具体范围见 1>整数范围):

   在32位平台上,`UInt`和`UInt32`长度相同。

   在64位平台上,`UInt`和`UInt64`长度相同。

  > 注意:尽量不要使用`UInt`,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。除了这种情况,最好使用`Int`,即使你要存储的值已知是非负的。

  统一使用`Int`可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推测,请参考[类型安全和类型推测](#type_safety_and_type_inference)。

2. 浮点数

 1> 浮点数概述

  浮点数是有小数部分的数字,比如`3.14159`,`0.1`和`-273.15`。

  浮点类型比整数类型表示的范围更大,可以存储比`Int`类型更大或者更小的数字。Swift 提供了两种有符号浮点数类型:

   `位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。

   `位浮点数。精度要求不高的话可以使用此类型。

  > 注意:`Double`精确度很高,至少有15位数字,而`Float`最少只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围。

03_Swift2基础之基本数据类型+相互转换

 2> 无穷(infinity)

  当数字超出Double范围的值被视为 无穷

03_Swift2基础之基本数据类型+相互转换

  上面是一个正无穷数, 自然还存在负无穷数, 如下图:

03_Swift2基础之基本数据类型+相互转换

  在Swift中还存在其他的一些奇特的类型, 大家感兴趣可以研究一下

03_Swift2基础之基本数据类型+相互转换

3. 布尔型

 1> 概述

  Swift 有一个基本的 _布尔(Boolean)_ 类型,叫做`Bool`。布尔值指_逻辑上的(logical)_,因为它们只能是真或者假。Swift 有两个布尔常量,`true`和`false`:

   let orangesAreOrange = true

   let turnipsAreDelicious = false

  `orangesAreOrange`和`turnipsAreDelicious`的类型会被推测为`Bool`. 因为它们的初值是布尔字面量。就像之前提到的`Int`和`Double`一样,如果你创建变量的时候给它们赋值`true`或者`false`,那你不需要将常量或者变量声明为`Bool`类型。

  初始化常量或者变量的时候如果所赋的值类型已知,就可以触发类型推测,这让 Swift 代码更加简洁并且可读性更高。

 2> 布尔值在判断语句中

  当你编写条件语句比如`if`语句的时候,布尔值非常有用:

   if turnipsAreDelicious {
         println("Mmm, tasty turnips!")
      } else {
         println("Eww, turnips are horrible.")
      }
      // 输出 "Eww, turnips are horrible."

  条件语句,例如`if`,请参考[控制流]。

  如果你在需要使用`Bool`类型的地方使用了非布尔值,Swift 的类型安全机制会报错。下面的例子会报告一个编译时错误:

   let i = 1

   if i {
          // 这个例子不会通过编译,会报错
      }

  然而,下面的例子是合法的:

   let i = 1
       if i == 1 {
         // 这个例子会编译成功
       }

  `i == 1`的比较结果是`Bool`类型,所以第二个例子可以通过类型检查。类似`i == 1`这样的比较,请参考[基本操作符]。

4. 数值类型转换

 通常来讲,即使代码中的整数常量和变量已知非负,也请使用`Int`类型。总是使用默认的整数类型可以保证你的整数常量和变量可以直接被复用并且可以匹配整数类字面量的类型推测。

  只有在必要的时候才使用其他整数类型,比如要处理外部的长度明确的数据或者为了优化性能、内存占用等等。

  使用显式指定长度的类型可以及时发现值溢出并且可以暗示正在处理特殊数据。

 1> 整数转换

  不同整数类型的变量和常量可以存储不同范围的数字。`Int8`类型的常量或者变量可以存储的数字范围是`-128`~`127`,而`UInt8`类型的常量或者变量能存储的数字范围是`0`~`255`。如果数字超出了常量或者变量可存储的范围,编译的时候会报错:

   let cannotBeNegative: UInt8 = -1  // UInt8 类型不能存储负数,所以会报错

   let tooBig: Int8 = Int8.max + 1 // Int8 类型不能存储超过最大值的数,所以会报错

  由于每种整数类型都可以存储不同范围的值,所以你必须根据不同情况选择性使用数值型类型转换。这种选择性使用的方式,可以预防隐式转换的错误并让你的代码中的类型转换意图变得清晰。

  要将一种数字类型转换成另一种,你要用当前值来初始化一个期望类型的新数字,这个数字的类型就是你的目标类型。

  在下面的例子中,常量`twoThousand`是`UInt16`类型,然而常量`one`是`Uint8`类型。它们不能直接相加,因为它们类型不同。所以要调用`UInt16(one)`来创建一个新的`UInt16`数字并用`one`的值来初始化,然后使用这个新数字来计算:

   let twoThousand: UInt16 = 2_000

   let one: UInt8 = 1

   let twoThousandAndOne = twoThousand + UInt16(one)

  现在两个数字的类型都是`UInt16`,可以进行相加。目标常量`twoThousandAndOne`的类型被推测为`UInt16`,因为它是两个`UInt16`值的和。

  `SomeType(ofInitialValue)`是调用 Swift 构造器并传入一个初始值的默认方法。

  在语言内部,`UInt16`有一个构造器,可以接受一个`UInt8`类型的值,所以这个构造器可以用现有的`UInt8`来创建一个新的`UInt16`。

  注意: 你并不能传入任意类型的值,只能传入`UInt16`内部有对应构造器的值。不过你可以扩展现有的类型来让它可以接收其他类型的值(包括自定义类型),请参考[扩展]。

 2> 整数和浮点数转换

  整数和浮点数的转换必须显式指定类型:

   let three = 3

   let pointOneFourOneFiveNine = 0.14159

   let pi = Double(three) + pointOneFourOneFiveNine

   // pi 等于 3.14159,所以被推测为 Double 类型

  这个例子中,常量`three`的值被用来创建一个`Double`类型的值,所以加号两边的数类型相同。如果不进行转换,两者无法相加。

  浮点数到整数的反向转换同样行,整数类型可以用`Double`或者`Float`类型来初始化:

   let integerPi = Int(pi)

   // integerPi 等于 3,所以被推测为 Int 类型

  当用这种方式来初始化一个新的整数值时,浮点值会被截断。也就是说`4.75`会变成`4`,`-3.9`会变成`-3`。

  > 注意:结合数字类 常量 和 变量 不同于 结合数字类 字面量。字面量`3`可以直接和字面量`0.14159`相加,因为数字字面量本身没有明确的类型。它们的类型只在编译器需要求值的时候被推测。