【问题标题】:Convert binary string to its complement将二进制字符串转换为其补码
【发布时间】:2020-04-05 03:10:41
【问题描述】:

我在 JavaScript 中有以下字符串: "1011100111100110101110110".

我想对它执行一个操作,这将返回它的补码(也就是所有的都被零替换,所有的零都被替换为一)。

javascript 文档说 NOT 运算符会做到这一点,但在我的测试中,它并没有给我预期的结果。

我想我的类型一开始就错了。

这是我的测试代码:

var nMyNumber = "1011100111100110101110110";
var sBinString = nMyNumber.toString(2);
console.log("Number: " + sBinString);

var reverse = ~sBinString;
console.log("Complement: " +  reverse);

【问题讨论】:

  • 你所拥有的不是“二进制”;它只是一串 1 和 0。所以二进制运算符不会像您认为的那样对实际二进制值起作用。你永远无法直接“看到”~ 处理的二进制类型,只能是它的一些抽象表示(例如整数)。
  • OK - 我知道类型不正确;我需要得到 nMyNumber 字符串的补码,然后将该结果转换为十进制...

标签: javascript


【解决方案1】:

只做字符串替换

var sBinString = nMyNumber
                .replace(/1/g,'x')//convert '1' to temp char('x')
                .replace(/0/g,'1')//convert '0' to '1'
                .replace(/x/g,'0')//finally convert temp char to '0'

【讨论】:

  • 为了避免需要温度,请参阅stackoverflow.com/a/10726800/7512 -- num = num.replace(/./g, function (c) { return { '0': '1', '1': '0' }[c];});
  • 哦,是的@slim 我认为这个答案也在这里,由 paranav 回答
  • @slim : num = num.replace(/./g, function (c) { return [1, 0][c]; });
【解决方案2】:

你的选角有误。一种解决方案是使用map

var nMyNumber = "1011100111100110101110110";
var reverse = nMyNumber.split('').map(x => x === "0" ? "1" : "0").join('');    
console.log("Number: " + reverse);

【讨论】:

  • 当我将此行添加到我的代码时出现错误:未捕获的类型错误:nMyNumber.map 不是函数。你试过了吗?
【解决方案3】:

如果你真的想要一个数字,首先将你的字符串转换成一个:

var x_as_binary_string = "1011100111100110101110110"
var x = parseInt(x_as_binary_string, 2);

现在要得到这个数字的补码,按照你说的使用 NOT:

var complement = ~ x;

如果您需要将其转换回二进制字符串:

var complement_as_string = complement.toString(2);

【讨论】:

  • 我也是这么想的:(~(parseInt("1011100111100110101110110", 2)) >>> 0).toString(2);
【解决方案4】:

字符串没有补码。 数字可以有二进制补码。如果您想要通过对恰好在字符串中的二进制值进行补充而产生的字符串,则必须编写自己的函数来执行此操作。一种方法是计算二进制字符串表示的值,对 that 进行补码,然后将该新数字转换为二进制字符串。

【讨论】:

    【解决方案5】:

    ~ Bitwise operator 不会为您提供预期的输出,因为它对带符号的 32 位表示中的每个位执行 NOT 运算,结果将转换回正常数字,因此您不会得到预期的结果。

    来自MDN docs

    所有位运算符的操作数都转换为二进制补码格式的有符号 32 位整数。二进制补码格式意味着数字的负数(例如 5 与 -5)是数字的所有位反转


    按位注意任何数字 x 产生 -(x + 1)。例如,~5 产生 -6。

    尽管它不会按预期工作,但您的代码中存在一些错误:

    1. nMyNumber.toString(2) 不会做任何事情,它返回相同的字符串。因此,您需要使用基数为2(二进制)的parseInt 转换为数字。
    2. 最后reverse 将保存一个以十进制格式记录的数字,以转换为二进制使用toString(2)(其中2 代表二进制格式,例如reverse.toString(2))。

    String#replace与回调函数一起使用,并在函数内根据匹配值返回字符。

    var nMyNumber = "1011100111100110101110110";
    
    console.log(
      nMyNumber.replace(/[01]/g, function(m) {
        return m == 0 ? '1' : 0;
      })
    )
    
    // with ES6 arrow function
    console.log(
      nMyNumber.replace(/[01]/g, m => m == 0 ? '1' : 0)
    )

    【讨论】:

      【解决方案6】:

      如何更简单的方法 ->

      var nMyNumber = "1011100111100110101110110";
      nMyNumber = nMyNumber.split("");
      var myNumber = [];
      for(var i=0;i<nMyNumber.length;i++) {
          if(nMyNumber[i] == 0) {
              myNumber.push(1);
          }
          if(nMyNumber[i] == 1) {
              myNumber.push(0);
          }
      }
      myNumber.join("");
      console.log(myNumber);
      

      【讨论】:

      • 怎么这么简单?简单到什么程度?
      • 更容易理解先生。毫无疑问,使用 map 函数会更短,但即使是函数调用也会使用匿名函数重复执行此操作。
      • 此代码不起作用。第二个if 应该是else if(或else),因为如果第一个条件匹配,则立即进行替换,因此也匹配第二个条件。最后,您有一个全为零的字符串...此外,Array.toString 方法将使用逗号连接条目,而带有空字符串作为参数的 Array.join 函数将提供预期结果
      猜你喜欢
      • 2016-07-16
      • 2020-03-05
      • 2016-08-31
      • 1970-01-01
      • 2015-04-19
      • 2020-11-26
      • 1970-01-01
      • 2013-09-28
      • 2021-02-24
      相关资源
      最近更新 更多