用Rust写平衡三进制加法器
1、三进制加法器的发展
最初的平衡三进制加法是采用了三选一结构(github原文),这位大佬也很厉害,他是硬件都弄了出来的,也写了虚拟机,甚至用这三态多路复用器弄出了可以存状态的硬件,但我没有去看了,因为当初刚开始的的一个全加器的方案(详情),都看了几天才懂,实在是不想费脑子了;不过也告诉我平衡三进制加法器确实存在,再后来,用图灵完备模拟了这结构,结果发现太复杂了,单1个零部件都好麻烦,然后幸运的推理出了与二进制相似的结构,即用2个平衡三进制半加器及1个平衡三进制调和门组成一器,哪时感觉牛呀;又后面,尝试用c++写这虚拟机,写着写着感觉很麻烦,就没写了,改用了rust来写,rust的好处就是它的变量是默认不会变的,写出来加法器后,在我眼中,数组就是平衡三进制逻辑门,平衡三进制就是数组,有关请看:平衡三进制存算一体架构
2、平衡三进制的二进制编码
转来转去的,目前最好实现的还是二进制,你想一下,一辆车走一条马路与两辆车走同一条马路并驱,速度是不是一样快,用空间来换时间还是很好用的,所以编码用来用去,还是方案二好用,如下所示:
二进制编码 | 平衡三进制表示 | 十进制 |
---|---|---|
00 | 0 | 0 |
01 | 1 | 1 |
10 | T | 2 |
11 | 未使用 | 未使用 |
3、平衡三进制逻辑门的转换
在上面用了2bit表示1trit,写虚拟机时发现8bit就是计算机的通用程序最小单位了,最主要的是它的移植性,所以都以1byte表示1trit,然后就是2表示的是-1、0表示0、1表示1,为什么这样映射,因为数组是从0开始的,不能以-1开始,然后这样就可以,将平衡三进制逻辑门进成数组的形式,而下图的三种逻辑门,就是组成全加器的关键,我们可以尝试转换。
例如,转换加和门:
逻辑加和 | 0 | 1 | 2 |
0 | 0 | 1 | 2 |
1 | 1 | 2 | 0 |
2 | 2 | 0 | 1 |
4、平衡三进制逻辑门的使用
现在的你,已经可以将数组变成逻辑门来使用了,所以我们尝试用rust,目标是写一个平衡三进制的多位加法器,先用1个加和门与1个共识门,组成1个平衡三进制半加器,然后再用2平衡三进制半加器和1个调和门,组成1个平衡三进制全加器,最后由多个全加器组成多位加法器;当然,这里是编程,我们只用到一个全加器,然后用while循环处理多位就好了,代码如下:
// **加和(TSUM)逻辑表 当为TT、01、10时出1,当为11、0T、T0时出T,其余为0 此门用于半加器的加和位处理 **
const TSUM:[[u8; 3];3]= [[0, 1, 2],[1, 2, 0],[2, 0, 1],
];
// **共识(TCONS)逻辑表 双T出T、双1出1、其余为0 此门用于半加器的进位处理 **
const TCONS:[[u8; 3];3]= [[0, 0, 0],[0, 1, 0],[0, 0, 2],
];
// **调和(TANY)逻辑表 当为TT、0T、T0时出T,当为11、01、10时出1,其余为0 此门用于全加器进位处理 **
const TANY:[[u8; 3];3]= [[0, 1, 2],[1, 1, 0],[2, 0, 2],
];/// 半加器:返回 (sum, carry)
pub fn ternary_half_adder(a: u8, b: u8) -> (u8, u8) {let sum = TSUM[a as usize][b as usize];// 和let carry=TCONS[a as usize][b as usize];// 进位;(sum, carry)
}
/// 全加器2:基于半加器实现
pub fn ternary_full_adder(a: u8, b: u8, c_in: u8) -> (u8, u8) {//2个平衡三进制半加器及1个平衡三进制调和门,组成一个平衡三进制全加器let (num,c1_in)=ternary_half_adder(a,b);let (sum,c2_in)=ternary_half_adder(num,c_in);let carry=TANY[c1_in as usize][c2_in as usize];//两个进位数合成一个进位数;(sum, carry)
}fn main() {let a = 1;let b = 1;let c=1;let (sum,carry)=ternary_half_adder(a, b);//半加器let (sum2,carry2)=ternary_full_adder(a, b, c);//平衡全加器println!("平衡半加器 sum:{} carry:{}",sum,carry);println!("平衡全加器 sum:{} carry:{}",sum2,carry2);
}
如上图所示,1+1=1T、1+1+1=10,运行结果也很正确。
5、平衡三进制多位加法器
其实上面的程序,可以更加简化,都已经将数组用成的逻辑门了,所以可以不用加和门、共识门、调和门什么的,直接面向结果编程,就像九九乘法表,所以用它的真值表,来写两个三维数组保存它的结果,直接调用这样就可以极大提升效率,平衡三进制全加真值表,如下所示:
所以就可以写出,如下代码:
// **全加器和(TFULLSUM) 逻辑表**
const TFULLSUM:[[[u8; 3];3];3] = [[[0, 1, 2],[1, 2, 0],[2, 0, 1],],[[1, 2, 0],[2, 0, 1],[0, 1, 2],],[[2, 0, 1],[0, 1, 2],[1, 2, 0],],
];
// **全加器进位(TFULLCONS) 逻辑表**
const TFULLCONS:[[[u8; 3];3];3] = [[[0, 0, 0],[0, 1, 0],[0, 0, 2],],[[0, 1, 0],[1, 1, 0],[0, 0, 0],],[[0, 0, 2],[0, 0, 0],[2, 0, 2],],
];/// 全加器:基于三维数组实现
pub fn ternary_full_adder(a: u8, b: u8, c_in: u8) -> (u8, u8) {let sum =TFULLSUM[a as usize][b as usize][c_in as usize];// 和let carry=TFULLCONS[a as usize][b as usize][c_in as usize];// 进位(sum, carry)
}fn main() {let a = 1;let b = 1;let c=1;let (sum2,carry2)=ternary_full_adder(a, b, c);//平衡全加器println!("平衡全加器 sum:{} carry:{}",sum2,carry2);}
结果正确,最后就多位相加的问题了,刚开始我也是想用for循环处理的,但太麻烦了,要用迭代器什么的,还要判断是否长度一样,它又是从低位加到高位的,所以我想很久,让我想到了一个优雅的方案--栈,栈这数据结构是先进后出,这样一个数如:1234与567,存入后再弹出就是4321与765,所以只要有两个栈协同弹出,先栈空的换成0,直到两栈都为空就完成了运算,巧的是,Rust标准库中Vec,天然就支持后进先出(LIFO),所以就可以写出,如下代码:
// **全加器和(TFULLSUM) 逻辑表**
const TFULLSUM:[[[u8; 3];3];3] = [[[0, 1, 2],[1, 2, 0],[2, 0, 1],],[[1, 2, 0],[2, 0, 1],[0, 1, 2],],[[2, 0, 1],[0, 1, 2],[1, 2, 0],],
];
// **全加器进位(TFULLCONS) 逻辑表**
const TFULLCONS:[[[u8; 3];3];3] = [[[0, 0, 0],[0, 1, 0],[0, 0, 2],],[[0, 1, 0],[1, 1, 0],[0, 0, 0],],[[0, 0, 2],[0, 0, 0],[2, 0, 2],],
];/// 全加器:基于三维数组实现
pub fn ternary_full_adder(a: u8, b: u8, c_in: u8) -> (u8, u8) {let sum =TFULLSUM[a as usize][b as usize][c_in as usize];// 和let carry=TFULLCONS[a as usize][b as usize][c_in as usize];// 进位(sum, carry)
}///多位三进制加法器基础,输入两个的三进制向量,返回加法结果向量和最终进位
pub fn ternary_stackadder_base(mut stack1: Vec<u8>,mut stack2: Vec<u8>,carry_in: u8)-> (Vec<u8>, u8){let mut result:Vec<u8> = Vec::new();//存储和let mut c_in:u8=carry_in;//Rust标准库中Vec,天然支持后进先出(LIFO),用栈协同弹出,倒序遍历, 支持不同长度while !stack1.is_empty() || !stack2.is_empty() {let v1 = stack1.pop().unwrap_or(0);let v2 = stack2.pop().unwrap_or(0);let (s_out, next_carry) =ternary_full_adder(v1, v2, c_in);result.push(s_out);//存结果c_in=next_carry;//进位传递}//result.push(c_in);可选,最高位溢出推入result.reverse(); // 反转,从高位到低位排列(result, c_in)
}//多位三进制加法器
pub fn ternary_stack_adder(stack1: Vec<u8>,stack2: Vec<u8>) -> Vec<u8> {let (mut result, carry) = ternary_stackadder_base(stack1,stack2, 0);result.insert(0, carry);result
}fn main() {let stack1=vec![0,1,1,1];let stack2=vec![0,2,0,0];let c:u8=1;let (sum,carry)=ternary_stackadder_base(stack1, stack2, c);println!("结果{}{:?}",carry,sum);}
结果正确,完结,撒花。。
6、平衡三进制逻辑门大全
数组就是逻辑门,算的快不如转的快,感觉忆阻器是很有前途,阻值没有负数,但是有0、1、2,这就已经够用了,不行还可以用,二位bit模拟1位平衡三进制数,管它那么多,先造出来再说,以下是平衡三进制的数组逻辑门大全,代码如下所示:
///*三进制逻辑门查找表声明**
///*2025/5/29**
///
/// 平衡三进制摩根定律及逻辑门转换图
/// TOR <-------> TNOR
/// ^ ^
/// | |
/// | |
/// v v
/// TNAND <-------> TAND// **非门(TNEG)逻辑表 输入T,输出1;输入0,输出0;输入1,输出T;**
pub const TNEG:[u8; 3]= [0, 2, 1];
// **右偏门(RIGHT_MUX)逻辑表(A+1) 输入T,输出0;输入0,输出1;输入1,输出T;**
pub const RIGHT_MUX:[u8; 3]= [1, 2, 0];
// **左偏门(LEFT_MUX)逻辑表(A-1) 输入T,输出1;输入0,输出T;输入1,输出0;**
pub const LEFT_MUX: [u8; 3]= [2, 0, 1];
// **最大门(MAX_MUX)逻辑表max(A,0) A与0比较,较大的输出 **
pub const MAX_MUX:[u8; 3]= [0, 1, 0];
// **最小门(MIN_MUX)逻辑表min(A,0) A与0比较,较小的输出 **
pub const MIN_MUX:[u8; 3]= [0, 0, 2];// **或门(TOR)逻辑表MAX(A,B) 有1出1、双T出T、其余为0 **
pub const TOR:[[u8; 3];3]= [[0, 1, 0],[1, 1, 1],[0, 1, 2],
];
// **与门(TAND)逻辑表MIN(A,B) 有T出T、双1出1、其余为0 **
pub const TAND:[[u8; 3];3]= [[0, 0, 2],[0, 1, 2],[2, 2, 2],
];
// **或非门(TNOR)逻辑表 有1出T、双T出1、其余为0 **
pub const TNOR:[[u8; 3];3]= [[0, 2, 0],[2, 2, 2],[0, 2, 1],
];
// **与非门(TAND)逻辑表 有T出1、双1出T、其余为0 **
pub const TNAND:[[u8; 3];3]= [[0, 0, 1],[0, 2, 1],[1, 1, 1],
];
// **异或门(TXOR)逻辑表 双T及双1出T、1T及T1出1、其余为0 **
pub const TXOR:[[u8; 3];3]= [[0, 0, 0],[0, 2, 1],[0, 1, 2],
];
// **同或门(TXNOR)逻辑表 双T及双1出1、1T及T1出T、其余为0 **
pub const TXNOR:[[u8; 3];3]= [[0, 0, 0],[0, 1, 2],[0, 2, 1],
];// **加和(TSUM)逻辑表 当为TT、01、10时出1,当为11、0T、T0时出T,其余为0 此门用于半加器的加和位处理 **
pub const TSUM:[[u8; 3];3]= [[0, 1, 2],[1, 2, 0],[2, 0, 1],
];
// **共识(TCONS)逻辑表 双T出T、双1出1、其余为0 此门用于半加器的进位处理 **
pub const TCONS:[[u8; 3];3]= [[0, 0, 0],[0, 1, 0],[0, 0, 2],
];
// **调和(TANY)逻辑表 当为TT、0T、T0时出T,当为11、01、10时出1,其余为0 此门用于全加器进位处理 **
pub const TANY:[[u8; 3];3]= [[0, 1, 2],[1, 1, 0],[2, 0, 2],
];// **全加器和(TFULLSUM) 逻辑表**
pub const TFULLSUM:[[[u8; 3];3];3] = [[[0, 1, 2],[1, 2, 0],[2, 0, 1],],[[1, 2, 0],[2, 0, 1],[0, 1, 2],],[[2, 0, 1],[0, 1, 2],[1, 2, 0],],
];
// **全加器进位(TFULLCONS) 逻辑表**
pub const TFULLCONS:[[[u8; 3];3];3] = [[[0, 0, 0],[0, 1, 0],[0, 0, 2],],[[0, 1, 0],[1, 1, 0],[0, 0, 0],],[[0, 0, 2],[0, 0, 0],[2, 0, 2],],
];
// **三与门(T3AND)逻辑表 有T出T、三1出1、其余为0 **
pub const T3AND:[[[u8; 3];3];3] = [[[0, 0, 2],[0, 0, 2],[2, 2, 2],],[[0, 0, 2],[0, 1, 2],[2, 2, 2],],[[2, 2, 2],[2, 2, 2],[2, 2, 2],],
];
// **三或门(T3AND)逻辑表 有1出1、三T出T、其余为0 **
pub const T3OR:[[[u8; 3];3];3] = [[[0, 1, 0],[1, 1, 1],[0, 1, 0],],[[1, 1, 1],[1, 1, 1],[1, 1, 1],],[[0, 1, 0],[1, 1, 1],[0, 1, 2],],
];