将二进制补码数转换为其二进制表示
Converting a Two's complement number to its binary representation
我正在执行按位运算,其结果显然存储为二进制补码。当我将鼠标悬停在它存储的变量上时,我看到 - num = -2086528968.
我想要的那个数字的二进制是 - (10000011101000100001100000111000)
。
但是当我说 num.toString(2)
我得到一个完全不同的二进制表示,原始数字的二进制而不是 2s comp(-1111100010111011110011111001000).
如何取回第一个字符串?
Link 到转换器:rapidtables.com/convert/number/decimal-to-binary.html
输入这个数字:-2086528968
按照下面的结果:
var number = -2086528968;
var bin = (number >>> 0).toString(2)
//10000011101000100001100000111000
console.log(bin)
pedro 已经回答了这个问题,但由于这是一个 hack,并不完全直观,我将对其进行解释。
I am performing bitwise operations, the result of which is apparently being stored as a two's complement number. When I hover over the variable its stored in I see 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"。您还记得我是怎么说 大多数 位运算 return 和 int32
的吗?有一种操作实际上 return 是一个 unsigned (32bit) 整数,即所谓的 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);
will I run this shifting code only when the number is negative, or always?
一般来说,运行 nr >>> 0
超过正整数没有坏处,但注意不要过大。
从技术上讲,JS 仅支持数字,即 double
个值 (64bit floating point
个值)。引擎内部也使用 int32
值;在可能的情况。但是没有 uint32
值。因此,当您将负 int32
转换为 uint32
时,引擎会将其转换为 double
。如果你跟进另一个位操作,它所做的第一件事就是将它转换回来。
所以当你需要一个实际的 uint32
值时这样做很好,比如在这里打印位,但你应该避免操作之间的这种转换。喜欢 "just to fix it".
我正在执行按位运算,其结果显然存储为二进制补码。当我将鼠标悬停在它存储的变量上时,我看到 - num = -2086528968.
我想要的那个数字的二进制是 - (10000011101000100001100000111000)
。
但是当我说 num.toString(2)
我得到一个完全不同的二进制表示,原始数字的二进制而不是 2s comp(-1111100010111011110011111001000).
如何取回第一个字符串?
Link 到转换器:rapidtables.com/convert/number/decimal-to-binary.html 输入这个数字:-2086528968
按照下面的结果:
var number = -2086528968;
var bin = (number >>> 0).toString(2)
//10000011101000100001100000111000
console.log(bin)
pedro 已经回答了这个问题,但由于这是一个 hack,并不完全直观,我将对其进行解释。
I am performing bitwise operations, the result of which is apparently being stored as a two's complement number. When I hover over the variable its stored in I see
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"。您还记得我是怎么说 大多数 位运算 return 和 int32
的吗?有一种操作实际上 return 是一个 unsigned (32bit) 整数,即所谓的 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);
will I run this shifting code only when the number is negative, or always?
一般来说,运行 nr >>> 0
超过正整数没有坏处,但注意不要过大。
从技术上讲,JS 仅支持数字,即 double
个值 (64bit floating point
个值)。引擎内部也使用 int32
值;在可能的情况。但是没有 uint32
值。因此,当您将负 int32
转换为 uint32
时,引擎会将其转换为 double
。如果你跟进另一个位操作,它所做的第一件事就是将它转换回来。
所以当你需要一个实际的 uint32
值时这样做很好,比如在这里打印位,但你应该避免操作之间的这种转换。喜欢 "just to fix it".