我希望看到二进制形式的正整数或负整数。
很像这个问题,但是是针对JavaScript的。
我希望看到二进制形式的正整数或负整数。
很像这个问题,但是是针对JavaScript的。
当前回答
我希望看到二进制形式的正整数或负整数。
这是一个老问题,我认为这里有很好的解决方案,但没有解释这些聪明的解决方案的使用。
首先,我们需要理解一个数字可以是正数也可以是负数。 此外,JavaScript提供了一个MAX_SAFE_INTEGER常量,其值为9007199254740991。这个数字背后的原因是JavaScript使用IEEE 754中指定的双精度浮点格式数字,并且只能安全地表示-(2^53 - 1)和2^53 - 1之间的整数。
所以,现在我们知道了数字“安全”的范围。此外,JavaScript ES6有内置方法number . issafeinteger()来检查一个数字是否是一个安全的整数。
逻辑上,如果我们想用二进制表示一个数字n,这个数字需要53位,但是为了更好的表示,让我们使用7组8位= 56位,并使用padStart函数根据其符号将左侧填充为0或1。
接下来,我们需要处理正数和负数:正数左边加0,负数左边加1。同样,负数将需要一个二补表示。我们可以很容易地通过添加Number来解决这个问题。MAX_SAFE_INTEGER + 1的数字。
例如,我们想将-3表示为二进制,让我们假设Number。MAX_SAFE_INTEGER = 00000000 11111111 (255) then Number。MAX_SAFE_INTEGER + 1将是00000001 00000000(256)。现在让我们加上数字number。MAX_SAFE_INTEGER + 1 -3,这将是00000000 11111101(253),但正如我们所说,我们将在左侧填充1,如11111111 11111101(-3),这在二进制中表示-3。
另一种算法是我们在数字上加1然后像这样求符号的倒数-(-3 + 1)= 2这将是00000000 00000010(2)现在我们像这样求每一位11111111 11111101(-3)我们又得到了-3的二进制表示。
下面是这些算法的工作代码片段:
function dec2binA(n) { if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer') if (n > 2**31) throw 'number too large. number should not be greater than 2**31' if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31' const bin = n < 0 ? Number.MAX_SAFE_INTEGER + 1 + n : n const signBit = n < 0 ? '1' : '0' return parseInt(bin, 10).toString(2) .padStart(56, signBit) .replace(/\B(?=(.{8})+(?!.))/g, ' ') } function dec2binB(n) { if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer') if (n > 2**31) throw 'number too large. number should not be greater than 2**31' if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31' const bin = n < 0 ? -(1 + n) : n const signBit = n < 0 ? '1' : '0' return parseInt(bin, 10).toString(2) .replace(/[01]/g, d => +!+d) .padStart(56, signBit) .replace(/\B(?=(.{8})+(?!.))/g, ' ') } const a = -805306368 console.log(a) console.log('dec2binA:', dec2binA(a)) console.log('dec2binB:', dec2binB(a)) const b = -3 console.log(b) console.log('dec2binA:', dec2binA(b)) console.log('dec2binB:', dec2binB(b))
其他回答
这是我的代码:
var x = prompt("enter number", "7");
var i = 0;
var binaryvar = " ";
function add(n) {
if (n == 0) {
binaryvar = "0" + binaryvar;
}
else {
binaryvar = "1" + binaryvar;
}
}
function binary() {
while (i < 1) {
if (x == 1) {
add(1);
document.write(binaryvar);
break;
}
else {
if (x % 2 == 0) {
x = x / 2;
add(0);
}
else {
x = (x - 1) / 2;
add(1);
}
}
}
}
binary();
函数 dec2bin(dec) { return (dec >>> 0).toString(2); } console.log(dec2bin(1));1 console.log(dec2bin(-1));11111111111111111111111111111111 控制台.log(dec2bin(256));100000000 console.log(dec2bin(-256));11111111111111111111111100000000
您可以使用Number.toString(2)函数,但它在表示负数时存在一些问题。例如,(-1). tostring(2)输出为“-1”。
要解决这个问题,可以使用无符号右移位操作符(>>>)将数字强制转换为无符号整数。
如果你运行(-1 >>> 0). tostring(2),你将把你的数字向右移动0位,这不会改变数字本身,但它将表示为一个无符号整数。上面的代码将正确地输出“111111111111111111111111111111111111111111111111”。
这个问题有进一步的解释。
-3 >>> 0(右逻辑移位)将其参数强制为无符号整数,这就是为什么你得到了-3的32位2的补数表示。
一个简单的方法就是……
Number(42).toString(2);
// "101010"
这是我常用的方法。这是一个非常快速和简洁的方法,适用于整数。
如果你愿意,这个方法也适用于bigint。你只需要把每个1变成1n。
// Assuming {num} is a whole number
function toBin(num){
let str = "";
do {
str = `${num & 1}${str}`;
num >>= 1;
} while(num);
return str
}
解释
这个方法,在某种程度上,遍历数字的所有位,就好像它已经是一个二进制数。
它以一个空字符串开始,然后将最后一位放在前面。Num & 1将返回数字的最后一位(1或0)。Num >>= 1然后删除最后一位,并将倒数第二位作为新的最后一位。重复这个过程,直到所有的位都被读取。
当然,这是对实际情况的极端简化。我是这样概括的。
对于32位来说,我想要的解决方案是这个答案末尾的代码,它来自developer.mozilla.org(MDN),但是添加了一些行,用于A)格式化和B)检查数字是否在范围内。
有些人建议使用x.toString(2),这对负号不起作用,它只是在负号中插入负号,这是不好的。
Fernando提到了一个简单的解决方案(x>>>0).toString(2);对于负数来说没问题,但是当x是正数时就有点问题了。它的输出从1开始,对于正数来说不是2s的补码。
任何不理解正数以0开始和负数以1开始的事实的人,在2s补中,可以在2s补中检查这个SO QnA。什么是“2的补”?
一个解决方案可能包括在正数前面加上一个0,这是我在这个答案的早期修订中所做的。我们有时可以接受一个33位的数字,或者我们可以确保要转换的数字在-(2^31)<=x<2^31-1的范围内。所以这个数字总是32位的。但是,您可以在mozilla.org上使用这个解决方案
Patrick的回答和代码很长,显然适用于64位,但有一个bug,评论者发现了,评论者修复了Patrick的bug,但Patrick在他的代码中有一些“神奇的数字”,他没有评论,已经忘记了,Patrick不再完全理解他自己的代码/为什么它可以工作。
安南有一些不正确和不清楚的术语,但提到了developer.mozilla.org的解决方案
注意-旧链接https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators现在重定向到其他地方,没有内容,但适当的旧链接,当archive.org检索页面时出现!,可在此下载https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
这里的解决方案适用于32位数字。
代码非常紧凑,只有三行函数。
但是我添加了一个正则表达式,以8位为一组格式化输出。基于如何用逗号作为千位分隔符格式化一个数字?(我只是修改了一下,从右到左按3秒分组,加逗号,到右到左按8秒分组,加空格)
并且,虽然mozilla对nMask的大小(输入的数字)做了一个评论..它必须在范围内,当数字超出范围时,他们没有测试或抛出错误,所以我添加了这个。
我不知道为什么他们将参数命名为“nMask”,但我将保持原样。
https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
function createBinaryString(nMask) { // nMask must be between -2147483648 and 2147483647 if (nMask > 2**31-1) throw "number too large. number shouldn't be > 2**31-1"; //added if (nMask < -1*(2**31)) throw "number too far negative, number shouldn't be < -(2**31)" //added for (var nFlag = 0, nShifted = nMask, sMask = ''; nFlag < 32; nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1); sMask=sMask.replace(/\B(?=(.{8})+(?!.))/g, " ") // added return sMask; } console.log(createBinaryString(-1)) // "11111111 11111111 11111111 11111111" console.log(createBinaryString(1024)) // "00000000 00000000 00000100 00000000" console.log(createBinaryString(-2)) // "11111111 11111111 11111111 11111110" console.log(createBinaryString(-1024)) // "11111111 11111111 11111100 00000000" //added further console.log example console.log(createBinaryString(2**31 -1)) //"01111111 11111111 11111111 11111111"