1、平衡三进制乘法表
前面写了平衡三进制的加法器,这个乘法器是在这基础上的,没看过的可以回去看看,说到乘法器还是要参考前苏联的资料的,平衡三进制的乘法也是很方便的,在平衡三进制基础中有详细讲过,下图就是资料:
也就是有(-1/0/1)这三相数互相相乘,结果得到的还是(-1/0/1),所以是很方便的,你认真看这乘法表其实就是逻辑表中的同或门(零乘任何数都为0,然后1*1与T*T结果都为1、最后是T*1或是1*T结果都为T),所以平衡三进制同或门等同于乘法表。
2、平衡三进制2位乘法器
这平衡三进制的乘法器,与二进制结构差不太多,也就是从低位到高位,依次相乘后相加与我们人类的计算一样,只过用一个用的是二进制,另一个用的是平衡三进制,原理结构图,如下所示:
用上面的思路,即AB*CD,得AC*100+10*(AD+BC)+BD,这三部分在不同的位置上,同或门完成的是AC相乘的结果,就是1位相乘的结果,它结果就是1trit,所以很有优势,也是只要半加器相加就可以,这样就可以写出,如下代码:
// **加和(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],
];
// **同或门(TXNOR)逻辑表 双T及双1出1、1T及T1出T、其余为0 此门相当于乘法表用于相乘处理 **
pub const TXNOR:[[u8; 3];3]= [[0, 0, 0],[0, 1, 2],[0, 2, 1],
];/// 半加器:返回 (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)
}
/// 全加器:基于半加器实现
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)
}
/// 2位乘法器
pub fn ternary_2trit_mul(a: u8, b: u8, c:u8, d:u8) -> (u8, u8,u8,u8) {//2个平衡三进制同或门及1个平衡三进制调和门,组成一个平衡三进制全加器let ac=TXNOR[a as usize][c as usize];let ad=TXNOR[a as usize][d as usize];let bc=TXNOR[b as usize][c as usize];let bd=TXNOR[b as usize][d as usize];let (num,carry)=ternary_half_adder(ad, bc);let (num2,carry2)=ternary_half_adder(ac, carry);(carry2,num2,num,bd)
}///多位三进制加法器基础,输入两个的三进制向量,返回加法结果向量和最终进位
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() {println!("结果{:?}",ternary_2trit_mul(1, 2, 2, 0));//1T(2)*T0(-3)=0T10(-9+3=-6)println!("结果{:?}",ternary_2trit_mul(2, 2, 1, 2));//TT(-4)*1T(2)=0T01(-9+1=-8)println!("结果{:?}",ternary_2trit_mul(1, 1, 1, 1));//11(4)*11(4)=1TT1(27-9-3+1=16)
}
结果正确。
3、平衡三进制多位乘法器
在这基础上实现多位乘法器,也是很简单的,可以用经典的“列乘法”逻辑,也就是被乘数是固定的,每个乘数单独相乘,得到多个部分积,最后移位后相加即可,详情请看计算机组成原理(九):乘法器,借用一下思路,如下所示:
A = 1101 (13 in decimal)
× B = 1011 (11 in decimal)
--------------1101 (部分积1)
+ 1101 (部分积2)
+ 0000 (部分积3)
+ 1101 (部分积4)
--------------10001111 (143 in decimal)
也就分别得到各个部分积,这也可用于平衡三进制,得代码如下所示:
// **全加器和(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],],
];
// **同或门(TXNOR)逻辑表 双T及双1出1、1T及T1出T、其余为0 此门相当于乘法表用于相乘处理 **
pub const TXNOR:[[u8; 3];3]= [[0, 0, 0],[0, 1, 2],[0, 2, 1],
];/// 全加器:基于三维数组实现
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_stack_adder(mut stack1: Vec<u8>,mut stack2: Vec<u8>)-> Vec<u8>{let mut result:Vec<u8> = Vec::new();//存储和let mut c_in:u8=0;//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
}///多位三进制乘法器基础
pub fn ternary_mul_base(stack1: Vec<u8>, stack2: Vec<u8>)-> Vec<u8>{let mut partials: Vec<Vec<u8>> = Vec::new();let mut shift = 0;//将 stack2 看作乘数,从低位到高位for &m2 in stack2.iter().rev(){//将 stack1 看作被乘数,固定不动let mut partial: Vec<u8> = stack1.iter().map(|&m1| TXNOR[m1 as usize][m2 as usize]).collect();// 在尾部精确补0partial.extend(vec![0; shift]);shift += 1;partials.push(partial);}//累加所有偏移乘积let mut result = vec![0];for partial in partials {result = ternary_stack_adder(result, partial);}result
}fn main() {let stack1=vec![1,1,0,1];let stack2=vec![1,0,1,1];let re=ternary_mul_base(stack1,stack2);print!("{:?}",re);
}
结果正确,1101(十进制31)*1011(十进制31)=1TTT0111(十进制1147)。
4、平衡三进制偏积表乘法器
从上面可以得知,它是用各个部分积累计相加得到结果的,也就是说只要得到,各个偏积就能有结果,比如:
A=1101(被乘数) B=1011(乘数)
1101 * 1=1101
1101 * 1=1101
1101 * 0=0000
1101 * 1=1101
所以,在平衡三进制中,有任何数0乘都得0,任何数乘1等于它本身,任何数乘T(-1)等于相反数,这样可构建出偏积表,有没有注意上多个部分积,只有1101与0000,它是二进制的,而对于平衡三进制它的结果有三种,即:0000、1101、2202,这个就是偏积表,用被乘数形成偏积表,乘数当成下标来调用偏积表,然后移位后相加就可以得到最后的结果,长的当被乘数好,这样算的快,这个版本比上面的版本好,代码如下所示:
// **全加器和(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],],
];
// **非门(TNEG)逻辑表 输入T,输出1;输入0,输出0;输入1,输出T;**
const TNEG:[u8; 3]= [0, 2, 1];/// 全加器:基于三维数组实现
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_stack_adder(mut stack1: Vec<u8>,mut stack2: Vec<u8>)-> Vec<u8>{let mut result:Vec<u8> = Vec::new();//存储和let mut c_in:u8=0;//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
}///多位三进制乘法器基础
pub fn ternary_mul_base(stack1: Vec<u8>, stack2: Vec<u8>)-> Vec<u8>{let partial_t: Vec<u8> = stack1.iter().map(|&m| TNEG[m as usize]).collect();// 构建偏积表:分别是乘以 0, 1, T 的情况let partials = vec![vec![0; stack1.len()], //0乘任何数,都得0stack1.clone(), //任何数乘1,等于它本身partial_t, //任何数乘T(-1)等于相反数];let mut result: Vec<u8> = vec![0];for (shift, &m2) in stack2.iter().rev().enumerate() {let mut part = partials[m2 as usize].clone();//用偏积表,m2当成下标,出可变副本part.resize(part.len() + shift, 0); // 更高效的偏移,低位补 0result = ternary_stack_adder(result, part);//加入当前部分积}result
}fn main() {let stack1=vec![1,1,0,1];let stack2=vec![1,0,1,1];let re=ternary_mul_base(stack1,stack2);print!("{:?}",re);
}
结果正确。