Javascript:添加两个二进制数(返回二进制)

时间:2016-11-01 01:39:02

标签: javascript binary numbers

我有二进制的两个输入,并且我也以二进制形式返回加法结果。

var addBinary = function(a, b) {
    var dec = Number(parseInt(a, 2)) + Number(parseInt(b, 2));
    return dec.toString(2);
};

对于像

这样疯狂的大二进制文件
  

a = 10100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101

     

b = 110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011

我正在输出

  

110111101100010011000101110110100000011101000101011000000000000000000000000000000000000000000000000

假定的正确输出是

  

110111101100010011000101110110100000011101000101011001000011011000001100011110011010010011000000000

是否因为溢出?如果是这样,Javascript对二进制加法溢出的限制是什么?对不起,有一堆1和0&#39。

15 个答案:

答案 0 :(得分:12)

我在Javascript中开发了二进制加法解决方案。

我最初的目标是通过在Javascript中复制数字二进制加法器电路中使用的机制来巩固我对二进制逻辑的理解(没有使用基本转换或按位运算符)。

您可以在CodePen找到原始项目的工作版本。

使用DOM做的事情比你可能需要的要多得多,但是当我插入你的数字时(通过下面提到的调整),我很高兴看到它有效!

Working Solution Code<<此项目是从我的原始项目修改而来,只包含输出正确答案所需的代码。

此解决方案假定ab是相同长度的字符串。要使用此解决方案,您的输入变量应修改为:

var a = "000010100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101"

var b = "110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011"

(我只是用零填充var a前面的缺失数字。)

如您所见,我重新创建了二进制加法器电路物理实现中使用的所有组件:

半加法器:

function halfAdder(a, b){
  const sum = xor(a,b);
  const carry = and(a,b);
  return [sum, carry];
}

Full Adder:

function fullAdder(a, b, carry){
  halfAdd = halfAdder(a,b);
  const sum = xor(carry, halfAdd[0]);
  carry = and(carry, halfAdd[0]);
  carry = or(carry, halfAdd[1]);
  return [sum, carry];
}

逻辑门:

function xor(a, b){return (a === b ? 0 : 1);}
function and(a, b){return a == 1 && b == 1 ? 1 : 0;}
function or(a, b){return (a || b);}

主要功能:

function addBinary(a, b){

  let sum = '';
  let carry = '';

  for(var i = a.length-1;i>=0; i--){
    if(i == a.length-1){
      //half add the first pair
      const halfAdd1 = halfAdder(a[i],b[i]);
      sum = halfAdd1[0]+sum;
      carry = halfAdd1[1];
    }else{
      //full add the rest
      const fullAdd = fullAdder(a[i],b[i],carry);
      sum = fullAdd[0]+sum;
      carry = fullAdd[1];
    }
  }

  return carry ? carry + sum : sum;
}

那么,addBinary(a,b)会产生正确答案!

var a = "000010100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101"
var b = "110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011"
var answer = "110111101100010011000101110110100000011101000101011001000011011000001100011110011010010011000000000";

console.log(addBinary(a, b) == answer); //true

我希望我在这里所做的一些事情对你也有用!

答案 1 :(得分:4)

这是我的看法:

逻辑很简单,就像上小学时的强硬派一样。您从最右边开始,所以我将第一个数字的最后一位和第二个数字的最后一位相加,并保留下一轮的进位。

在每个回合中(在while内),我都对两个数字进行了修剪,例如:

// number
1101 -> 110
// The math is simple: 1101/10|0 (divide by 10 and convert to integer)

result变量是一个 String ,因此很容易在不进行任何数学运算的情况下向其添加数字。

完整代码:

function binaryAddition(a,b){
  var result = "",
      carry = 0;
  
  while(a || b || carry){
    let sum = a%2 + b%2 + carry; // get last digit from each number and sum everything

    if( sum > 1 ){  
      result = sum%2 + result; 
      carry = 1;
    }
    else{
      result = sum + result;
      carry = 0;
    }
    
    // trim last digit (110 -> 11)
    a = a/10|0; 
    b = b/10|0;
  }
  
  return +result;
}


// Tests
[
  [0,0],
  [1,1],
  [1,0],
  [0,1],
  [10,1],
  [11,1],
  [10,10],
  [111,111],
  [1010,11]
].forEach(numbers => 
   document.write("<br>"+
     numbers[0] + " + " + 
     numbers[1] + " = " + 
     binaryAddition(numbers[0], numbers[1])
   )
)

答案 2 :(得分:2)

忘记Javascript的操作精确度,考虑如何在数学中加一个二进制文件。

例如,H:\users>dir /a-d/b/s H:\users\UserWithFiles\ToBeMoved\moveme.txt + np.argmax

首先,我们应该从右到左开始。 现在我们得到了 In [21]: import numpy as np In [22]: df['doc_type'] = pd.Series(np.argmax(df[["a_score", "b_score"]].values, axis=1)).replace({0: 'a', 1: 'b'}) In [23]: df Out[23]: a_id a_score b_id b_score doc_type 0 A 1 a 0.10 a 1 B 2 b 0.20 a 2 C 3 c 3.10 b 3 D 4 d 4.10 b 4 2 e 5.00 b 5 F f 5.99 a 6 G 7 NaN a 在那之后,我们转到下一个。 11 如果我们使用Javascript,如何获得结果。

我们知道,10可以获得剩余号码, 1 + 0 = 1 可以获得号码。 在十进制系统中,我们得到 1 + 1 = 10 ,如何将Mod转移到Division。 我们可以使用

1 + 1 = 2

现在我们可以将两个字符串连接在一起。

2

所以我们的最终代码可以是:

10

答案 3 :(得分:2)

支持不同长度的二进制字符串的通用解决方案

我已将padZeroes()函数添加到Cassandra Wilcox's nice answer以创建支持不同长度的二进制字符串的通用解决方案

我已经针对add binary problem上的leetcode对此解决方案进行了测试,因此它应该非常强大。

/**
 * @param {string} a
 * @param {string} b
 * @return {string}
 */

// logic gates
function xor(a, b) {
  return a === b ? 0 : 1;
}

function and(a, b) {
  return a == 1 && b == 1 ? 1 : 0;
}

function or(a, b) {
  return a || b;
}

function halfAdder(a, b) {
  const sum = xor(a, b);
  const carry = and(a, b);
  return [sum, carry];
}

function fullAdder(a, b, carry) {
  halfAdd = halfAdder(a, b);
  const sum = xor(carry, halfAdd[0]);
  carry = and(carry, halfAdd[0]);
  carry = or(carry, halfAdd[1]);
  return [sum, carry];
}

function padZeroes(a, b) {
  const lengthDifference = a.length - b.length;
  switch (lengthDifference) {
    case 0:
      break;
    default:
      const zeroes = Array.from(Array(Math.abs(lengthDifference)), () =>
        String(0)
      );
      if (lengthDifference > 0) {
        // if a is longer than b
        // then we pad b with zeroes
        b = `${zeroes.join('')}${b}`;
      } else {
        // if b is longer than a
        // then we pad a with zeroes
        a = `${zeroes.join('')}${a}`;
      }
  }
  return [a, b];
}

function addBinary(a, b) {
  let sum = '';
  let carry = '';

  const paddedInput = padZeroes(a, b);
  a = paddedInput[0];
  b = paddedInput[1];

  for (let i = a.length - 1; i >= 0; i--) {
    if (i == a.length - 1) {
      // half add the first pair
      const halfAdd1 = halfAdder(a[i], b[i]);
      sum = halfAdd1[0] + sum;
      carry = halfAdd1[1];
    } else {
      // full add the rest
      const fullAdd = fullAdder(a[i], b[i], carry);
      sum = fullAdd[0] + sum;
      carry = fullAdd[1];
    }
  }
  return carry ? carry + sum : sum;
}

答案 4 :(得分:1)

在我看来,这是因为那些数字太大而不能失去精确度。

var addBinary = function(a, b) {
    var dec = Number(parseInt(a, 2)) + Number(parseInt(b, 2));
    console.log("the number a is " + parseInt(a, 2));
    console.log("the number b is " + parseInt(b, 2));
    console.log("the dec is  " + dec);
    return dec.toString(2);
};
var a = "10100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101"
var b = "110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011"
console.log(addBinary(a, b));

结果是

the number a is 2.484789315402498e+28
the number b is 5.2670055459872975e+29
the dec is  5.515484477527547e+29
110111101100010011000101110110100000011101000101011000000000000000000000000000000000000000000000000

你可以看到numa并麻木两种损失精度。如果将最后的结果转换为二进制:

 parseInt("110111101100010011000101110110100000011101000101011000000000000000000000000000000000000000000000000", 2)

然后你得到:

 5.515484477527547e+29. 

所以“toString(2)”的过程是正确的。

我们手动模拟二进制的过程来解决这个问题(假设输入字符串是正确的,所以我的代码中没有捕获任何异常。运行时环境是nodejs v4.6.0):

"use strict"
let addBinarybyChainhelen = function(a, b) {
    let alen = a.length;
    let blen = b.length;

    let i = alen - 1;
    let j = blen - 1;

    let result  = "";
    let carry   = 0;

    while(i >= 0 && j >= 0) {
        let acur = parseInt(a[i], 10);
        let bcur = parseInt(b[j], 10);

        let rcur = (acur + bcur + carry) % 2;
        carry = parseInt((acur + bcur + carry) / 2); 

        result += rcur;

        i--;
        j--;
    }

    while(i >= 0) {
        let acur = parseInt(a[i], 10);
        let rcur = (acur + carry) % 2;
        carry = parseInt((acur + carry) / 2); 

        result += rcur;
        i--;
    }

    while(j >= 0) {
        let bcur = parseInt(b[j], 10);
        let rcur = (bcur + carry) % 2;
        carry = parseInt((bcur + carry) / 2); 

        result += rcur;
        j--;
    }

    if(carry) {
        result += carry;
    }

    return result.split("").reverse().join("");
}


// use the function
let a = "10100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101" 
let b = "110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011"
console.log(addBinarybyChainhelen(a, b))

并获得正确的输出

110111101100010011000101110110100000011101000101011001000011011000001100011110011010010011000000000

答案 5 :(得分:1)

受@ thepatriot的启发,我制作了单线版本:

var addBinary = function(a, b) {
  return (BigInt(`0b${a}`) + BigInt(`0b${b}`)).toString(2);
};

console.log(addBinary('10100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101','110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011'));

答案 6 :(得分:0)

这是我的尝试...没有什么简单的逻辑。

var addBinary = function(a, b) {
  let aLast = a.length - 1;
  let bLast = b.length - 1;

  let carry = 0;
  let aStr = [];

  while(aLast>=0 || bLast>=0){
    let sum = carry;
    if(aLast >= 0) {
      sum+= Number(a[aLast]);
      aLast--;
    }

    if(bLast >= 0) {
      sum+= Number(b[bLast]);
      bLast--
    }
    aStr.push(sum%2);
    carry = Math.floor(sum/2);
  }

  if(carry)     aStr.push(carry);

  return aStr.reverse().join("");
};

答案 7 :(得分:0)

我也想添加我的解决方案

let a = '1111';
let b = '1111';
let addBinary = (a, b) => {

  let highestNumber;
  let lowestNumber;
  let answer = '';
  let carry = 0;

	let aArr = a.split('');
  let bArr = b.split('');
  
  if(aArr.length > bArr.length) {
  
  	highestNumber = aArr;
    lowestNumber = bArr;
  } else {
  
  	highestNumber = bArr;
    lowestNumber = aArr;
  }
  
  let diff = highestNumber.length - lowestNumber.length;
  let startingInd = highestNumber.length - diff;
  
  
  for(let i= startingInd; i < highestNumber.length; i++) {
  
  	lowestNumber = ['0'].concat(lowestNumber);
    
  }
  
  
  for(let i=highestNumber.length-1; i >= 0; i--) {
    
    let num1 = parseInt(highestNumber[i]);
    let num2 = parseInt(lowestNumber[i]);
    let sum = num1 + num2 + carry;
    
    let currValue = sum === 1 || sum === 3 ? '1' : '0';
    
    answer = currValue.concat(answer);
    
    
    if(sum === 3 || sum === 2) carry = 1;
    
  }
  
  if(carry == 1) answer = '1'.concat(answer);
  if(carry == 2) answer = '10'.concat(answer);
  
  return answer;
  
};


console.log(addBinary(a, b));

答案 8 :(得分:0)

这是我的解决方案,使用了一些条件语句。

function addBinary(a, b) {
  let result = "";
  let i = a.length - 1;
  let j = b.length - 1;
  let carry = 0;

  while (i >= 0 || j >= 0 || carry > 0) {
    const x = parseInt(a[i], 10) || 0;
    const y = parseInt(b[j], 10) || 0;
    const z = x + y + carry;
    i--, j--;

    // error handling: non-binary number
    if (z > 3 || z < 0) return console.error("non-binary number");

    result = z === 3 || z === 1 ? 1 + result : 0 + result;
    carry = z < 2 ? 0 : 1;
  }

  return result;
}

条件语句的逻辑与使用以下开关/情况相同:

switch (z) {
   case 3:
      result = 1 + result;
      carry = 1;
      continue;
   case 2:
      result = 0 + result;
      carry = 1;
      continue;
   case 1:
      result = 1 + result;
      carry = 0;
      continue;
   case 0:
      result = 0 + result;
      carry = 0;
      continue;
   default:
      return console.error("non-binary number");
}

答案 9 :(得分:0)

我想提出ES6中最短的变体(主要要求是“避免使用内置的大整数来解决此难题”):

// It's my challenge solution with 104 chars only:
addBinaryStrings = ([...a], [...b]) => {
    c = 0
    r = ''
    while (a[0] | b[0] | c) {
        c += ~~a.pop() + ~~b.pop()
        r = c%2 + r
        c = c > 1
    }
    return r
}

// Test:
binaryString1 = "1010110000000001101011001000010110101111110010100011011100101010000101011010001110011001011110111"
binaryString2 = "10100110100001100010010001111100001110100110111001100001011010011000101111001110100011101110000100100010001100110000001010011000100110"

string1.innerText = binaryString1;
string2.innerText = binaryString2;
expected.innerText = "10100110100001100010010001111100001111111100111001101110110011011011100101001100111000001001101001110010111000000001111101100100011101"
result.innerText = addBinaryStrings(binaryString1, binaryString2)
* {
  font-family: monospace;
}

div b {
  color: red;
}
div span {
  color: dodgerblue;
}
<div>BINARY&nbsp;1:&nbsp;<b id="string1"></b></div>
<div>SUMM&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;<span>+</span></div>
<div>BINARY&nbsp;2:&nbsp;<b id="string2"></b></div>
<div>FINALLY&nbsp;:&nbsp;<span>=</span></div>
<div>EXPECTED:&nbsp;<span id="expected"></span></div>
<div>RESULT&nbsp;&nbsp;:&nbsp;<span id="result"></span></div>

答案 10 :(得分:0)

只需转换为 int 并再次转换为 bin

var addBinary = (a, b) => {
    var dec = Number(parseInt(a, 2)) + Number(parseInt(b, 2));
    return (dec >>> 0).toString(2);
};

console.log(addBinary(1000,11));

答案 11 :(得分:0)

你可以像下面那样解决它:

[12608, 10069, 310695, 57509]
[12808, 10269, 310895, 57709]
[13108, 10569, 311195, 58009]

就这样

答案 12 :(得分:0)

parseInt 可能导致大于最大整数的问题。

解决方案是BigInt

(BigInt('0b' + a) + BigInt('0b' + b)).toString(2);

几乎类似于

(parseInt(a, 2) + parseInt(b, 2)).toString(2)

但它可以处理更多。

答案 13 :(得分:-1)

这是一个简单的解决方案,给定ab是两个二进制字符串,也以二进制字符串返回它们的sum

let addBinary = (a, b) => {
  // handle corner cases when either input is empty
  if (a === null || a.length === 0) return b;
  if (b === null || b.length === 0) return a;

  let i = a.length - 1;
  let j = b.length - 1;
  let carry = 0;
  let sum = '';

  while (i >=0 || j >= 0) {
    let x = i < 0 ? 0 : +a[i];
    let y = j < 0 ? 0 : +b[i];
    let val = x + y + carry;

    carry = val > 1 ? 1 : 0;
    sum = val % 2 + sum;

    i--;
    j--;
  }

  return carry > 0 ? carry + sum : sum;
};

关于二进制加法的一些基本规则:

  • 0 + 0 = 0
  • 0 + 1 = 1
  • 1 + 0 = 1
  • 1 + 1 = 0,carry = 1

希望这会有所帮助!

答案 14 :(得分:-1)

用于添加2个n长度二进制整数的简单和朴素的解决方案:

function binaryAddition(num1, num2) {
  let result = [];
  let carry = 0;
  for(let i = num1.length-1; i >= 0; i--) {
    if((num1[i] === 1 && num2[i] === 1)) {
      if(carry) {
       result.unshift(1) 
      } else {
       result.unshift(0);  
      }
      carry = 1;
    } else if((num1[i] === 0 && num2[i] === 0)) {
      if(carry) {
       result.unshift(1) 
      } else {
       result.unshift(0);  
      } 
      carry = 0;
    } else if((num1[i] === 1 && num2[i] === 0) || (num1[i] === 0 && num2[i] === 1)) {
      if(carry) {
       result.unshift(0)
       carry = 1;
      } else {
       result.unshift(1);  
      }
    }  
  }
  if(carry) result.unshift(1);
  return result;
}