整数。
编译器会对此类型作特殊处理,并用高效实现覆盖它。运行时对 Int 使用特殊表示:直接存储“小”有符号数,而较大的数使用快速任意精度算术库(通常是 GMP)。“小数”是可用比平台指针大小少一位编码的整数(即 64 位架构上为 63 位,32 位架构上为 31 位)。
整数是包含正负的完整数字。 整数是任意精度的,仅受运行 Lean 的硬件能力的限制;对于编程和计算机科学中使用的固定宽度整数,请参阅定精度整数章节。
Lean 的实现对整数提供了特殊支持。 整数的逻辑模型基于自然数:每个整数被建模为自然数或自然数的负后继。 整数上的操作是使用该模型指定的,该模型用于内核和解释代码中。 在这些语境中,整数代码继承了自然数特殊支持带来的性能优势。 在编译后的代码中,整数被表示为高效的任意精度整数,并且足够小的数字被存储为不需要通过指针间接引用的值。 算术操作由利用这些高效表示的原语实现。
整数既可以表示为一个自然数,也可以表示为一个自然数后继的否定。
整数的这种表示方式具有许多有用的属性。
它使用和理解起来相对简单。
与符号和 Nat 构成的有序对不同,0 有一个唯一的表示形式,这简化了关于等式的推理。
整数也可以表示为一对自然数,其中一个减去另一个,但这需要一个行为良好的商类型,并且由于需要证明函数尊重等价关系,使用商类型可能会非常繁琐。
像自然数一样,足够小的整数无需指针即可表示:对象指针中的最低位用于指示该值实际上不是指针。 如果一个整数太大,无法放入剩余的位中,它将作为一个普通的 Lean 对象分配,该对象由对象头和任意精度整数组成。
OfNat Int 实例允许数字在表达式和模式语境中用作字面量。
(OfNat.ofNat n : Int) 规约为构造子应用 Int.ofNat n。
Neg Int 实例也允许使用否定。
在这些实例之上,构造子 Int.negSucc 还有一套特殊语法,可在打开 Int 命名空间时使用。
记号 -[ n +1] 让人联想到 -(n + 1),这也是 Int.negSucc n 的含义。
将任意精度整数转换为机器字大小的有符号整数,上溢或下溢时回绕。
运行时会用高效实现覆盖此函数。
将任意精度整数转换为 8 位整数,上溢或下溢时回绕。
示例:
Int.toInt8 48 = 48
Int.toInt8 (-115) = -115
Int.toInt8 (-129) = 127
Int.toInt8 (128) = -128
将任意精度整数转换为 16 位整数,上溢或下溢时回绕。
示例:
Int.toInt16 48 = 48
Int.toInt16 (-129) = -129
Int.toInt16 (128) = 128
Int.toInt16 70000 = 4464
Int.toInt16 (-40000) = 25536
将任意精度整数转换为 32 位整数,上溢或下溢时回绕。
示例:
Int.toInt32 48 = 48
Int.toInt32 (-129) = -129
Int.toInt32 70000 = 70000
Int.toInt32 (-40000) = -40000
Int.toInt32 2147483648 = -2147483648
Int.toInt32 (-2147483649) = 2147483647
将任意精度整数转换为 64 位整数,上溢或下溢时回绕。
运行时会用高效实现覆盖此函数。
示例:
Int.toInt64 48 = 48
Int.toInt64 (-40_000) = -40_000
Int.toInt64 2_147_483_648 = 2_147_483_648
Int.toInt64 (-2_147_483_649) = -2_147_483_649
Int.toInt64 9_223_372_036_854_775_808 = -9_223_372_036_854_775_808
Int.toInt64 (-9_223_372_036_854_775_809) = 9_223_372_036_854_775_807
通常,使用 Lean 的重载算术记号来访问整数上的算术操作。
特别是,Add Int、Neg Int、Sub Int 和 Mul Int 实例允许使用普通的插缀运算符。
除法稍微复杂一些,因为整数上有多种合理的除法概念。
Div Int 和 Mod Int 实例实现了欧几里得除法,在 Int.ediv 的参考中有描述。
然而,这并不是唯一合理的除法舍入和余数约定。
有四对除法和取模函数可用,它们实现了各种约定。
使用 T 舍入约定的整数取模。
在 T 舍入约定(截断除法)下,所有舍入都趋向零。除以 0 定义为 0,且 Int.tmod a 0 = a。
在此约定下,Int.tmod a b + b * (Int.tdiv a b) = a。此外,Int.natAbs (Int.tmod a b) = Int.natAbs a % Int.natAbs b;当 b 不整除 a 时,Int.tmod a b 与 a 同号。
编译器会用高效实现覆盖此函数;这里给出的是逻辑模型。
示例:
Int 上的按位运算符可以理解为对整数的二进制补码表示的无限位流进行按位操作。
Int 上的相等和不等测试通常使用其相等和排序关系的可判定性,或者使用 BEq Int 和 Ord Int 实例来执行。
整数的非严格不等式,通常通过 ≤ 运算符使用。
把 a ≤ b 定义为 b - a ≥ 0,其中使用 Int.NonNeg。