我正在执行按位运算,其结果显然存储为二进制补码。当我将鼠标悬停在变量上时,它会存储在-num = -2086528968.
我想要的那个数字的二进制是-(10000011101000100001100000111000)
。
但是当我说num.toString(2)
时,我得到了完全不同的二进制表示形式,即原始数字的二进制而不是2s comp(-1111100010111011110011111001000)。
我如何找回第一个字符串?
链接到转换器:Rapidtables.com/convert/number/decimal-to-binary.html 请输入此号码:-2086528968
答案 0 :(得分:3)
遵循以下结果:
var number = -2086528968;
var bin = (number >>> 0).toString(2)
//10000011101000100001100000111000
console.log(bin)
答案 1 :(得分:2)
pedro已经回答了这个问题,但是由于这是黑客行为,而且不完全直观,因此我将对其进行解释。
我正在执行按位运算,其结果显然存储为二进制补码。当我将鼠标悬停在变量上时,会看到
num = -2086528968
否,大多数位运算的结果都是32位带符号整数。这意味着0x80000000
位将被解释为符号,后跟31位值。
奇怪的位序列是因为JS如何对值进行字符串化,例如sign + Math.abs(value).toString(base)
;
如何处理?我们需要告诉JS 不将该位解释为符号,但作为值的一部分。但是如何?
一个易于理解的解决方案是将0x100000000
添加到负数,从而获得正数。
function print(value) {
if (value < 0) {
value += 0x100000000;
}
console.log(value.toString(2).padStart(32, 0));
}
print(-2086528968);
另一种方法是分别转换低位和高位
function print(value) {
var signBit = value < 0 ? "1" : "0";
var valueBits = (value & 0x7FFFFFFF).toString(2);
console.log(signBit + valueBits.padStart(31, 0));
}
print(-2086528968);
//or lower and upper half of the bits:
function print2(value) {
var upperHalf = (value >> 16 & 0xFFFF).toString(2);
var lowerHalf = (value & 0xFFFF).toString(2);
console.log(upperHalf.padStart(16, 0) + lowerHalf.padStart(16, 0));
}
print2(-2086528968);
另一种方式涉及pedro使用的“ hack”。您还记得我曾说过 most 位操作返回一个int32
吗?实际上有一个操作会返回 unsigned (32位)整数,即所谓的Zero-fill right shift。
所以number >>> 0
不会更改数字的位,但是不再将第一位解释为符号。
function uint32(value){
return value>>>0;
}
function print(value){
console.log(uint32(value).toString(2).padStart(32, 0));
}
print(-2086528968);
仅当数字为负数或始终为负数时,我才运行此移位代码吗?
通常来说,在正整数上运行nr >>> 0
并没有什么害处,但请注意不要过度使用它。
从技术上讲,JS仅支持数字,即double
值({64bit floating point
值)。引擎内部还使用int32
值;在可能的情况。但是没有uint32
值。因此,当您将否定的int32
转换为uint32
时,引擎会将其转换为double
。而且,如果您再进行一次位操作,那么它要做的第一件事就是将其转换回去。
因此可以在需要实际uint32
值的情况下执行此操作,例如在此处打印位,但是最好避免在两次操作之间进行这种转换。就像“只是修复它”。