tft每日頭條

 > 生活

 > js正數轉負數的函數

js正數轉負數的函數

生活 更新时间:2025-01-04 20:09:41

js正數轉負數的函數?為什麼要做js位運算呢?ECMAScript 整數有兩種類型,即:,接下來我們就來聊聊關于js正數轉負數的函數?以下内容大家不妨參考一二希望能幫到您!

js正數轉負數的函數(負數轉16進制依據的規則)1

js正數轉負數的函數

背景

為什麼要做js位運算呢?

  • 因為最近在學習hash算法,裡面用到了大量的位運算
  • 另外網上也找了很多資料,但大都比較片面,沒有說明特殊情況時的處理,換幾組數據計算結果就出錯。

重溫整數

ECMAScript 整數有兩種類型,即:

  • 有符号整數(允許用正數和負數)
  • 無符号整數(隻允許用正數) 在 ECMAScript 中,所有整數字面量默認都是有符号整數,這意味着什麼呢?

有符号整數使用 31 位表示整數的數值,用第 32 位表示整數的符号,0 表示正數,1 表示負數。

數值範圍從 -2147483647 到 2147483647。

位運算會把二進制數限制在32位,超出部分會被舍棄

調試位運算常用的幾個方法

toString(2)

轉換成2進制字符串

var a = 1732584193;a.toString(2); // 1100111010001010010001100000001

parseInt(‘11001’, 2)

将2進制字符串轉換成10進制數

parseInt('11001', 2) // 25

padStart(32, ‘0’)

字符串總長度,左邊不足位數補0

'1100000001'.padStart(32, 0) // 00000000000000000000001100000001

源碼、反碼、補碼

源碼

将數字轉換成的2進制數, 最左邊表示符号位,1負數,0正數

5 源碼: 0101-10 源碼:11010

反碼

正數的反碼與其原碼相同

負數的反碼,除符号位外,其他位取反

5 源碼:0101反碼:0101-10源碼:11010 反碼:10101

補碼

正整數的補碼與其原碼相同

負整數的補碼,取反碼+1

5源碼:0101補碼:0101-10源碼:11010補碼:10110

ok,現在開始正題

位運算符

  • 非(~)
  • 與(&)
  • 或(|)
  • 異或(^)
  • 帶符号左移(<<)
  • 帶符号右移(>>)
  • 無符号右移(>>>)

位運算符:非(~)

運算步驟:

  1. 将該數字取負數
  2. 然後減1
~25 // -26

過程:

  • 25取負:-25
  • 減1:-26
~1  // -2~-1 // 0~100 // -101~-100 // 99

位運算符:與(&)

運算步驟:

  1. 把兩個數轉換成2進制補碼
  2. 相同位置進行比較(同為1,結果為1,否則為0)
  3. 如果計算結果是負數,還要再做補碼處理

如果位數不夠,正數左邊補0,負數補1

正正運算

10 & 3 // 2

過程:

  • 10 補碼:1010
  • 3 補碼:0011
  • 結果:0010,即 2

正負運算(1)

14 & -13 // 2

過程:

  • 14 補碼:01110(補一位符号位)
  • -13 源碼:11101,補碼:10011
  • 與運算:00010,即 2

正負運算(2)

88 & -19 // 72

過程:

  • 88 補碼:01011000(補一位符号位)
  • -19 源碼:110011,補碼:101100
  • 01011000 & 101100
  • 負數(101100)位數不夠,左邊補1,即11101100
  • 也就是 01011000 & 11101100
  • 結果為:01001000,即:72

負負運算

-12 & -5 // -16

過程:

  • -12 補碼:10100
  • -5 補碼:11011
  • 與運算:10000
  • 結果為負,再取一次補碼: 110000:-16

練習

3 & 7-21 & 16-271733879 & -17325841941125899778533470 & 81293020 & 0xF48192342 & 0xFFFF

位運算符:或(|)

運算步驟:

  1. 把兩個數字轉換成2進制補碼
  2. 相同位置進行比較(有一個是1,結果即為1)
  3. 如果計算結果是負數,還要再做補碼處理

正正運算

10 | 3 // 11

過程:

  • 10 源碼:1010
  • 3 源碼:0011
  • 結果:1011,即 11

正負運算

10 | -3 // -1

過程:

  • 10補碼:01010
  • -3補碼:11101
  • 或運算:11111
  • 結果為負,再取碼:10001,即:-1

負負運算

-15 | -21 // -5

過程:

  • -15 補碼:110001
  • -21 補碼:101011
  • 或運算:111011
  • 結果為負再取補碼:10101,即:-5

練習

15 | 2040 | -14-271733879 | 1732584193(-271733879 & -1732584194) | (~-271733879 & 271733878)

位運算符:異或(^)

運算步驟:

  1. 把兩個數轉換成2進制補碼
  2. 相同位置進行比較(必須是0和1或者1和0,結果才為1)
  3. 如果結果為負,再取補碼

正正異或

10 ^ 3 // 9

過程:

  • 10 補碼:1010
  • 3 補碼:0011
  • 結果:1001,即 9

正負異或

10 ^ -3 // -9

過程:

  • 10 補碼: 01010
  • -3 補碼:11101
  • 異或運算:10111
  • 結果為負,再取補碼:11001,即-9

負負異或

-10 ^ -3 // 11

過程:

  • -10 補碼:10110
  • -3 補碼:11101
  • 異或運算:01011,即:11

練習

5 ^ 8-10 ^ 9-13 ^ -20-271733879 ^ -1732584194 ^ 271733878

位運算符:帶符号左移(<<)

運算步驟:

  1. 把數字轉換成2進制補碼
  2. 左移指定位數,右邊補0
  3. 如果結果未負數,再取補碼

超過32位的部分舍棄

正數左移

1 << 2 // 補碼:00000001 左移2位, 即 00000100,結果為:45 << 3 // 補碼:00000101 左移3位, 即 00101000,結果為:40 

可以看出,正數帶符号左移,即 a << n,其實是 a * 2的n次幂

負數左移

-3 << 4

  • -3 補碼:101
  • 左移4位 1010000
  • 标志位為負,取補碼:1110000,即-48
-6 << 3  // 1010 << 3 等于 1010000,取補碼,1110000 即:-48-11 << 4 // 10101 << 4 等于 101010000,取補碼,110110000 即:-176

邊緣情況

情況1:正數變負數

1732584193 << 2  // -1659597820

計算過程

  • 1732584193轉換成2進制源碼:1100111010001010010001100000001(31位)
  • 左移2位,補2個0:110011101000101001000110000000100(33位)
  • 移除左邊多餘的1位:10011101000101001000110000000100(32位)
  • 變為負數,取補碼:11100010111010110111001111111100
  • 即:-1659597820

情況2:負數變正數

-1732584193 << 2  // 1659597820

計算過程

  • -1732584193轉換成2進制:11100111010001010010001100000001(32位)
  • 負數,取補碼:10011000101110101101110011111111(32位)
  • 左移2位:1001100010111010110111001111111100(34位)
  • 多餘部分舍棄:01100010111010110111001111111100(32位)
  • 符号位為正,無需再補碼,即:1659597820

練習

1 << 32 1 << 33 1 << 402147483648 << 21732584193 << 6

位運算符:帶符号右移(>>)

運算步驟:

  1. 取數字二進制補碼
  2. 右移指定位數,左邊補位與符号位一緻
  3. 多餘位被舍棄
  4. 如果計算結果為負,再取補碼

正數右移

5 >> 1 // 0101 右移1位 0010,即 21 >> 2 // 0001 右移1位 0000,即 0

正數右移比較簡單,移出的内容直接舍棄即可,左邊用0補充

負數右移

-5 >> 2 // -2

分析:

  • -5 補碼:1011
  • 右移2位:1110
  • 結果為負,取補碼:1010,即-2

練習

5 + 64 >> 91732584193 >> 4

位運算符:無符号右移(>>>)

運算步驟:

  1. 把數字轉換成32位2進制補碼
  2. 連同符号位,右移動指定的位數
  3. 向右被移出的位被丢棄,左側用0填充

因為符号位變成了 0,所以結果總是正的

正數右移

正數時候 >> 和 >>> 結果是一樣的

5 >> 2 // 101 右移2位 001 即:15 >>> 2 // 101 右移2位 001 即:1

負數右移

-5 >>> 2 // 1073741822

過程:

  • -5 源碼: 10000000 00000000 00000000 00000101
  • 補碼:11111111 11111111 11111111 11111011
  • 右移兩位:00111111 11111111 11111111 11111110
  • 轉換成十進制即為:1073741822

問題:為什麼這個要補滿32位,而之前的運算都沒有?

因為之前的運算,正數補的都是0,負數雖然補1,但計算後要做補碼,補位的數最終不影響計算

而無符号右移,則會影響運算。所以需要補全

練習

-23 >>> 245678765 >>> 31

關于位運算的核心思路

  • 運算前要取補碼
  • 運算結果導緻負數,再取一次補碼

以上内容都是個人收集、以及多次嘗試整理的。

因為網上看到的很多文章計算方式都不對,雖然舉的例子沒問題,但換機組數字就計算錯誤。

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved