小作坊自主下料
近期挺好奇累加器的,好奇是怎么算出1+1=10的,在本子上画了一下
输入1 | 输入2 | 输出 |
---|---|---|
0 | 0 | 00 |
1 | 0 | 01 |
0 | 1 | 01 |
1 | 1 | 10 |
只保留低位
输入1 | 输入2 | 输出低位 | 异或 |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 1 | 1 |
0 | 1 | 1 | 1 |
1 | 1 | 0 | 0 |
看规律异或就行
异或的规则是相同为0,不同为1
只保留高位
输入1 | 输入2 | 输出高位 | 与 |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 |
0 | 1 | 0 | 0 |
1 | 1 | 1 | 1 |
看结果就是按与计算,结果就是高位,结合高低位,就是第一张表的结果
此时一个一位计算器就完事了
//js代码
let add = (a,b) => ((a & b) + '' + (a ^ b));
add(0,0);//=>00
add(0,0);//=>01
add(0,1);//=>01
add(1,1);//=>10
正规作坊下料
怎么看都有点不对,印象里累加器好像很大的样子,我这个好像太过简单了
一查发现我这个设计只能计算一位数据,并且无法串联计算,模块需要一个进位标识符,然后将其串起来,即可算很多位,
其思想是只计算低位结果,输入两个加数和一个进位,输出一个结果和进位,将进位串入下一个输入里
//js
//a 加数1
//b 加数2
//c 是否进位
let add = (a,b,c) => {
let low = a ^ b;//低位(直接结果)
let tall = a & b;//高位(是否可能进位)
let sum = low ^ c;//结果(考虑进位后的结果)
//计算是否进位
let isCarry = low & c;//计算进位+低位(直接结果)
let cNext = tall | isCarry;
return { cNext, sum };
}
add(1,1);//=>{cNext: 1, sum: 0}
add(1,0);//=>{cNext: 0, sum: 1}
add(0,0);//=>{cNext: 0, sum: 0}
此时我们就拥有一个完整功能的累加器了,实现其串联功能,只需要将add串起来,从代码上可以这样理解
//js
//累加全部,只接收二进制
let addAll = (a,b) => {
let sa = String(a);
let sb = String(b);
let length = sa.length -1;
let isCarry = 0;
let sums = '';
for(i = 0; i <= length; i++){
let bita = sa[length - i];
let bitb = sb[length - i];
let outo = add(bita, bitb, isCarry);//调用累加器
//console.log('计算输入和输出',bita,bitb,isCarry,outo)
sums = outo.sum + '' + sums;
isCarry = outo.cNext;
//console.log('是否进位,输出的数', isCarry,sums)
}
//console.log('补上进位的数', isCarry)
sums = isCarry + '' + sums;//补上最后一个进位
console.log('运算结果',sums);
}
addAll(11,11);//=>运算结果 110
addAll(110,101);//=>运算结果 1011