Мы можем прочитать об операторе правого сдвига >>
на MDN
... знак результирующего числа такой же, как знак первого операнда.
Однако 3332508426 >> 24 === -58
в моем Chrome 127.0.6533.120.
Как это можно объяснить?
Кстати, 3332508426
— это десятичное представление IP 198.162.11.10
.
Нет, я не понимаю, почему 3332508426 >> 24 === -58 (почему оператор >> изменил знак числа)
const n2ip=n=>n.toString(16).padStart(8,'0').match(/.{2}/g).map(s=>parseInt(s,16)).join('.');
Спасибо за функцию преобразования номера в IPv4, но это не основная тема моего поста.
и именно поэтому я разместил это в комментарии, а не в Ответах...
Битовые манипуляции в Javascript работают с 32-битными целыми числами со знаком.
1<<31
например дает -2147483648
Однако числовые значения используют точность с плавающей запятой double
(64 бит IEEE754), поэтому проблем с записью, например, нет.
x = 2147483648
и если вы отобразите x
, вы получите 2147483648
(целые числа представляются без потери точности до ∓2⁵³ = ∓9007199254740992... намного больше, чем 32 бита).
Например, просто сдвинув x
на НОЛЬ мест, вы получите -2147483648.
x << 0
возвращается -2147483648
потому что вычисление выполняется с использованием 32-битных целых чисел со знаком.
3332508426 — это HEX C6A20B0A. Если это интерпретируется как 32-битное целое число, старший бит равен 1, поэтому он отрицателен. Переключение вправо сохраняет знак.
Я не понимаю, почему вы написали, каково шестнадцатеричное представление моего номера.
@ Borneo777 Мне было интересно, единственное, что я могу придумать, это то, что C
в двоичном формате - это 1100
, а самый левый бит - это 1
, и, возможно, он придерживается старой школы и имеет преобразование HEX в BIN-попугай. Конечно, это работает только для прямого порядка байтов (то, что использует Javascript), для прямого порядка байтов вам нужно будет выбрать предпоследний шестнадцатеричный символ, а затем первый левый бит четырехбитного бита. Это своего рода то, что сделало HEX популярным в старом ассемблере и т. д., HEX в BIN было проще, чем DEC в BIN и т. д. IOW: если первое дополненное 0 значение HEX равно 8-F
, это отрицательное число.
Верно, Кит. У C старший бит = 1, вероятно, не все сразу это понимают (кстати, это не оскорбление). Это мой аппаратный опыт ;-)
@LexW. спасибо за ваше объяснение
MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Right_shift#description
Оператор
>>
перегружен для двух типов операндов: числового и BigInt. Для чисел оператор возвращает 32-битное целое число.
Поскольку 3332508426
уже является 32-битным целым числом, оно использует это значение. Однако 32-битные числа имеют знак, а 32-битное двоичное представление самого левого бита вашего числа равно 1, то есть является отрицательным значением.
9 (base 10): 00000000000000000000000000001001 (base 2)
-9 (base 10): 11111111111111111111111111110111 (base 2)
Решение состоит в том, чтобы сначала преобразовать ваш номер в BigInt
, а затем конвертировать обратно, то есть:
let result = Number(BigInt(3332508426) >> BigInt(24));
console.info(result);
console.info(Number((BigInt(3332508426) >> BigInt(16)) % BigInt(1<<8)))
console.info(Number((BigInt(3332508426) >> BigInt(8)) % BigInt(1<<8)))
console.info(Number(BigInt(3332508426) % BigInt(1<<8)))
Другие объяснили, почему это отрицательно, но если вы сразу после извлечения байтов из Uint32,..
Другой вариант, вместо смещения битов: если вы хотите извлечь байты из Uint32, создайте UInt32Array с одним значением, а затем преобразуйте его в Uint8Array для извлечения байтов.
например.
const a = new Uint8Array(new Uint32Array([3332508426]).buffer);
console.info(`${a[3]}.${a[2]}.${a[1]}.${a[0]}`);
объяснил что? преобразование целых чисел в IP-адрес?