如何在Z3的BitVec中全程使用2位向量实现模3加法运算?
在Z3的2位BitVec中实现模3加法运算
完全可以全程用2位BitVec实现(a+b)%3的功能,核心是直接基于模3加法的真值表推导逻辑表达式,跳过先做3位加法再取模的步骤——毕竟模3的有效值只有0、1、2,刚好能被2位无符号BitVec完全覆盖(00=0,01=1,10=2,11在模3语境下等价于0)。
推导逻辑表达式
假设输入a的两位为a1 a0,输入b的两位为b1 b0,输出结果c=(a+b)%3的两位为c1 c0,先列出完整的真值表:
| a(十进制) | b(十进制) | c=(a+b)%3 | a1a0 | b1b0 | c1c0 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 00 | 00 | 00 |
| 0 | 1 | 1 | 00 | 01 | 01 |
| 0 | 2 | 2 | 00 | 10 | 10 |
| 1 | 0 | 1 | 01 | 00 | 01 |
| 1 | 1 | 2 | 01 | 01 | 10 |
| 1 | 2 | 0 | 01 | 10 | 00 |
| 2 | 0 | 2 | 10 | 00 | 10 |
| 2 | 1 | 0 | 10 | 01 | 00 |
| 2 | 2 | 1 | 10 | 10 | 01 |
基于真值表可推导出输出位的布尔表达式:
c0 = (a0 XOR b0) XOR (a1 AND b1)c1 = (a1 XOR b1) AND NOT (a0 AND b0)
Z3实现代码
直接用Z3的BitVec操作实现上述逻辑,全程仅使用2位BitVec:
from z3 import * def mod3_add(a, b): # 提取输入的每一位 a0 = Extract(0, 0, a) a1 = Extract(1, 1, a) b0 = Extract(0, 0, b) b1 = Extract(1, 1, b) # 计算输出的两个位 c0 = XOR(XOR(a0, b0), And(a1, b1)) c1 = And(XOR(a1, b1), Not(And(a0, b0))) # 合并为2位BitVec返回 return Concat(c1, c0) # 测试所有可能的输入组合 test_cases = [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)] for a_val, b_val in test_cases: a = BitVecVal(a_val, 2) b = BitVecVal(b_val, 2) res = simplify(mod3_add(a, b)) expected = (a_val + b_val) % 3 print(f"({a_val}+{b_val})%3 = {expected}, 计算结果: {res.as_long()}")
运行这段代码会输出所有测试用例的结果,完全符合模3加法的预期,且全程没有用到3位BitVec,完美满足你的效率需求。
内容的提问来源于stack exchange,提问作者Chao Xu
相关产品推荐
相关产品推荐

