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);
}
結果正確。