以 10 为基数到以 2 为基数的数字转换如何工作?

Posted

技术标签:

【中文标题】以 10 为基数到以 2 为基数的数字转换如何工作?【英文标题】:How does base 10 number to base 2 number conversion work? 【发布时间】:2014-07-03 08:28:43 【问题描述】:

我正在尝试理解以下代码,该代码可在 MDN 和相关question 的答案中找到。 (仅在 FF 30 中测试。)

function createBinaryString (nMask) 
    // nMask must be between -2147483648 and 2147483647
    for (var nFlag = 0, nShifted = nMask, sMask = ""; nFlag < 32;
        nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
    return sMask;

var p = createBinaryString(7);
console.log(p); //"00000000000000000000000000000111"

这个在MDN 上,但它是如何工作的 - 如果有任何可以理解的解释,我将不胜感激。 我有二元运算符的基本知识并且知道有一个.toString(2) 方法。但是String(nShifted &gt;&gt;&gt; 31) 部分究竟做了什么?

这里有更好的可读版本,但第一个不起作用。在这里,我也将不胜感激有关我做错了什么的任何建议。我看不出与第二个工作版本有什么不同。

var re = '';
var numb = 7;
var shiftBuf = numb;
for (var i = 0; i < 32; i++); 
   re += String(shiftBuf >>> 31);
   shiftBuf <<= 1;

console.log(re); //"0" 

var result = '';
var num = 7;
var shiftBuffer = num;
for (var i = 0; i < 32; i++) 
   result += String(shiftBuffer >>> 31);
   shiftBuffer <<= 1;

console.log(result); //"00000000000000000000000000000111"

【问题讨论】:

Rq : 你有一个 ;结束你的第一个 for 循环。 【参考方案1】:

这里的重要假设是初始数字小于 2^32。在这种情况下,它只是在二进制表示中检索一个又一个数字。

re += String(shiftBuf >>> 31);
shiftBuf <<= 1;

第一行将shiftBuf 向右移动31 个位置添加到re,第二行将shiftBuf 向左移动。所以基本上它只是得到数字。这是一个例子。如果shiftBuf = 7;,那么在二进制表示中它是111。添加缺失的零,你就有了

00000000000000000000000000000111

一步一步:

[0] shiftBuf >>> 31 produces 0  // picks first digit if shiftBuf < 2^32
[0] result is now "0"
[0] shitBuffer <<= 1 produces 00000000000000000000000000001110

[1] shiftBuf >>> 31 produces 0
[1] result is now "00"
[1] shitBuffer <<= 1 produces 00000000000000000000000000011100

[2] shiftBuf >>> 31 produces 0
[2] result is now "000"
[2] shitBuffer <<= 1 produces 00000000000000000000000000111000

...

[30] shiftBuf >>> 31 produces 1
[30] result is now "0000000000000000000000000000011"
[30] shitBuffer <<= 1 produces 10000000000000000000000000000000

[31] shiftBuf >>> 31 produces 1
[31] result is now "00000000000000000000000000000111"
[31] shitBuffer <<= 1 produces 00000000000000000000000000000000

至于你的第二个问题:这两个代码之间的区别在于第一个代码中有for (var i = 0; i &lt; 32; i++);(注意末尾的分号)。后面的代码(括号 中的代码)不会在循环中运行。它只运行一次。

【讨论】:

我开始明白了。所以它从数字的数字表示的左到右。移位运算符总是“产生” 0 或 1?为什么?或者这就是 String(shiftBuf >>> 31) 的奇迹? @malte 移位运算符并不总是产生 0 或 1。但如果我们处理小于 2^32 的数字(即 32 位二进制数),则向右移动 31 次会给我们留下1 位:0 或 1。因此,如果一个数字大于 2^32,那么该算法将不起作用(由于另一个原因,它不会起作用:二进制和移位运算符仅适用于 2^32 以内的整数) . 同样向左移动仅适用于最大 2^32 的整数。从移位运算符的角度来看,每个数字都是一个 32 位(带有前导零)的二进制数。向左或向右移动不会影响位数(就像在我的示例中一样)。

以上是关于以 10 为基数到以 2 为基数的数字转换如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

我应该在基数排序中使用哪个基数?以及如何在基数之间转换?

将基数为 10 的数字转换为 .NET 中任何基数的最快方法?

将一个以 10 为底的数字转换为 N

以其他基数表示负数

线性时间的基数排序与将输入转换为适当的基数

从十进制基数转换为十六进制基数c ++