Mojo 中的所有值都分配有相对应的数据类型,大多数类型都是由结构体定义的标称的类型。这些类型是标称的(或“命名的”),因为类型相等性是由类型的名称而不是其结构决定的。
有一些类型未定义为结构,例如下面的两种情况:
- 函数是根据其签名进行输入的。
- NoneType是一种具有一个实例(即None对象)的类型,用于表示“无值”。
Mojo附带了一个标准库,提供了许多有用的类型和实用函数。这些标准类型不是特权类型。每个标准库类型的定义都与用户定义类型一样,甚至包括 Int和 等基本类型String。但这些标准库类型是在大多数 Mojo 程序中使用的构建块。
最常见的类型是内置类型,它们始终可用且无需导入。这些类型包括数值(numeric)、字符串(strings)、布尔值(boolean)等类型。
标准库还包含许多可根据需要导入的类型,包括集合(collection)类型、用于与文件系统交互和获取系统信息的实用程序等。
Numeric types
它表示系统支持的最大尺寸的有符号整数——通常为 64 位或 32 位。
Mojo 还具有各种精度的整数和浮点值的内置类型:
Type name | Description |
---|---|
Int8 | 8-bit signed integer |
UInt8 | 8-bit unsigned integer |
Int16 | 16-bit signed integer |
UInt16 | 16-bit unsigned integer |
Int32 | 32-bit signed integer |
UInt32 | 32-bit unsigned integer |
Int64 | 64-bit signed integer |
UInt64 | 64-bit unsigned integer |
Float16 | 16-bit floating point number (IEEE 754-2008 binary16) |
Float32 | 32-bit floating point number (IEEE 754-2008 binary32) |
Float64 | 64-bit floating point number (IEEE 754-2008 binary64) |
表 1.具有特定精度的数字类型
表 1 中的类型实际上都是单一类型的别名, SIMD稍后将讨论。
所有数字类型都支持常见的数字和位运算符。math模块提供了许多附加数学函数。
您可能想知道何时使用Int以及何时使用其他整数类型。通常,Int当您需要整数类型并且不需要特定位宽时,这是一个不错的安全默认设置。将其用作IntAPI 的默认整数类型可使 API 更加一致和可预测。
Floating-point numbers
浮点类型表示实数。由于并非所有实数都能用有限位数表示,因此浮点数无法准确表示每个值。表 1 中列出的浮点类型Float64— 、Float32和 Float16— 遵循 IEEE 754-2008 标准来表示浮点值。每种类型都包含一个符号位、一组表示指数的位和另一组表示分数或尾数的位。表 2 显示了每种类型在内存中的表示方式。
Type name | Sign(符号) | Exponent(指数) | Mantissa(尾数) |
---|---|---|---|
Float64 | 1 bit | 11 bits | 52 bits |
Float32 | 1 bit | 8 bits | 23 bits |
Float16 | 1 bit | 5 bits | 10 bits |
表 2.浮点类型的详细信息
指数值为全 1 或全 0 的数字表示特殊值,允许浮点数表示无穷大、负无穷大、有符号零和非数字 (NaN)。有关如何表示数字的更多详细信息,请参阅Wikipedia 上的IEEE 754。
对于浮点值,有几点需要注意:
- 四舍五入误差,四舍五入可能会产生意外结果。例如,1/3 无法在这些浮点格式中准确表示。对浮点数执行的运算越多,四舍五入误差就越大。
- 连续数字之间的间距。连续数字之间的间距在浮点数格式的范围内是可变的。对于接近零的数字,连续数字之间的距离非常小。对于较大的正数和负数,连续数字之间的间距大于 1,因此可能无法表示连续的整数。
由于这些值是近似值,因此用相等运算符 ( ==) 进行比较很少有用。请注意以下示例:
var big_num = 1.0e16
var bigger_num = big_num+1.0
print(big_num == bigger_num)
运行结果为:True
较运算符(< >=等等)适用于浮点数。您还可以使用该math.isclose()函数比较两个浮点数在指定的公差范围内是否相等。
Numeric literals
除了这些数字类型之外,标准库还提供整数和浮点文字类型, IntLiteral以及 FloatLiteral。
这些文字类型在编译时用于表示代码中出现的文字数字。一般来说,您永远不应该自己实例化这些类型。
表 3 总结了可以用来表示数字的文字格式。
Format | Examples(例子) | Notes(注释) |
---|---|---|
Integer literal | 1760 | Integer literal, in decimal format.(整数文字,十进制格式。) |
Hexadecimal literal | 0xaa, 0xFF | Integer literal, in hexadecimal format.Hex digits are case-insensitive.(整数文字,采用十六进制格式。十六进制数字不区分大小写。) |
Octal literal | 0o77 | Integer literal, in octal format.(整数文字,八进制格式。) |
Binary literal | 0b0111 | Integer literal, in binary format.(整数文字,二进制格式。) |
Floating-point literal | 3.14, 1.2e9 | Floating-point literal.Must include the decimal point to be interpreted as floating-point.(浮点文字。必须包含小数点才能解释为浮点。) |
表 3.数字文字格式
在编译时,文字类型是任意精度(也称为无限精度)值,因此编译器可以执行编译时计算而不会出现溢出或舍入错误。
在运行时,这些值将转换为有限精度类型——Int对于整数值,Float64对于浮点值。(将只能在编译时存在的值转换为运行时值的过程称为具体化。)
以下代码示例显示了任意精度计算与运行时使用值进行的相同计算之间的差异Float64,后者存在舍入误差。
var arbitrary_precision = 3.0 * (4.0 / 3.0 - 1.0)
# use a variable to force the following calculation to occur at runtime
var three = 3.0
var finite_precision = three * (4.0 / three - 1.0)
print(arbitrary_precision, finite_precision)
运行结果如下图:
SIMD and DType
为了支持高性能数字处理,Mojo 使用类型 SIMD作为其数字类型的基础。SIMD(单指令、多数据)是一种处理器技术,允许您一次对整个操作数集执行操作。Mojo 的 SIMD类型抽象了 SIMD 操作。一个SIMD值表示一个 SIMD 向量— 即一个固定大小的值数组,可以放入处理器的寄存器中。SIMD 向量由两个参数定义 :
- 一个DType值,定义向量中的数据类型(例如,32 位浮点数)。
- 向量中元素的数量,必须是 2 的幂。
var vecr = SIMD[DType.float32, 4](3.0, 2.0, 2.0, 1.0)
对 SIMD 值的数学运算以元素为单位应用于向量中的每个单独元素。例如:
var vec1 = SIMD[