如何正确执行64位算术?Agda中64位无符号整数算术处理方法
在Agda中处理64位算术的解决方案
嘿,针对你提出的两个64位算术相关问题,我来分享下在Agda里的实用处理方式:
1. 正确执行64位算术的通用方式
在Agda里做64位算术,最稳妥的路径有两种,按需选择:
- 优先用标准库/成熟第三方库:Agda的官方标准库(
agda-stdlib)已经封装了全套固定宽度数值类型及运算,不用自己从零造轮子:- 64位有符号整数:用
Data.Int.Int64(部分新版本标准库支持),自带合规的加减乘除等运算,严格遵循有符号64位的溢出规则。 - 64位浮点数:
Data.Float模块的Float类型对应IEEE 754双精度(也就是64位浮点),包含所有基础浮点运算。 - 64位无符号整数:后面会专门讲,其实标准库也有现成实现。
- 64位有符号整数:用
- 自定义实现(特殊需求场景):如果需要定制溢出行为、添加额外证明逻辑,可以基于
Fin类型手动构建64位数值类型。比如用Fin 2^64表示无符号64位整数,然后自己实现加法、乘法等运算,同时用Agda的证明能力验证运算的正确性。不过这种方式比较繁琐,只推荐给有特殊需求的场景。
2. 64位无符号整数(uint64)算术的处理方法
你说没找到64位无符号整数的运算原语,大概率是没注意到标准库的Data.Word模块——这里面的Word64就是专门为64位无符号整数设计的,而且自带全套原语级运算:
- 导入并直接使用标准库:在你的Agda文件顶部导入模块,就能直接用现成的运算:
这些运算都是基于编译器后端的原生64位无符号操作实现的,自动处理无符号溢出(按模2^64规则),效率和正确性都有保障。open import Data.Word using (Word64; _+_; _-_; _*_; _div_; _mod_; _∧_; _∨_; _xor_; shiftL; shiftR) - 定制溢出行为(如果需要):如果不想默认的模运算,而是要检测溢出,可以基于
Word64封装逻辑。比如写一个带溢出标志的加法:
你还可以用Agda的证明能力,进一步验证这个溢出检测逻辑的正确性。open import Data.Bool using (Bool) open import Data.Nat using (ℕ; _+_; _>_) open import Data.Word using (Word64; _+_; toℕ; fromℕ) private max-uint64 : ℕ max-uint64 = 18446744073709551615 -- 2^64 - 1 addWithOverflow : Word64 → Word64 → (Word64 × Bool) addWithOverflow a b = let sum = a + b overflow = toℕ a + toℕ b > max-uint64 in (sum, overflow) - 替代方案:基于Fin类型手动定义:如果因为某些原因无法使用标准库的
Word64,可以用Fin (2^64)来表示无符号64位整数,然后利用Fin类型自带的模运算特性实现算术操作。不过这种方式需要编写大量的证明代码来保证运算合规,远不如直接用标准库高效。
内容的提问来源于stack exchange,提问作者MaiaVictor




