用Rust写平衡三进制加法器

发布于:2025-06-27 ⋅ 阅读:(13) ⋅ 点赞:(0)

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],
    ],
];


网站公告

今日签到

点亮在社区的每一天
去签到