JavaScript 進位轉換&位運算,瞭解一下?

来源:https://www.cnblogs.com/chanwahfung/archive/2020/02/22/12345838.html
-Advertisement-
Play Games

前言 在一般的代碼中很少會接觸到進位和位運算,但這不代表我們可以不去學習它。作為一位編程人員,這些都是基礎知識。如果你沒有學過這方面的知識,也不要慌,接下來的知識並不會很難。本文你將會學習到: 進位轉換 按位操作符 Javascript進位轉換 手動實現進位轉換 進位轉換 以下使用常見的十進位和二進 ...


前言

在一般的代碼中很少會接觸到進位和位運算,但這不代表我們可以不去學習它。作為一位編程人員,這些都是基礎知識。如果你沒有學過這方面的知識,也不要慌,接下來的知識並不會很難。本文你將會學習到:

  • 進位轉換
  • 按位操作符
  • Javascript進位轉換
  • 手動實現進位轉換

進位轉換

以下使用常見的十進位和二進位轉換作為例子,其他進位的轉換也是大同小異,感興趣可以自己琢磨下。

十進位轉二進位

根據 “逢十進一” 的法則進行計數時,每十個相同的單位組成一個和它相鄰的較高的單位,這種計數法叫做十進位計數法,簡稱十進位。這種是我們最常用的計數法。

整數

整數使用 “除二取餘,逆序排列” 來轉換為二進位,下麵是18轉換為二進位的例子:

// 除二取餘
18 / 2 = 9...0
 9 / 2 = 4...1
 4 / 2 = 2...0
 2 / 2 = 1...0
 1 / 2 = 0...1

// 倒序排列
10010

就這麼簡單,將得出的餘數逆序排列,即可得出18的二進位表示

小數

小數使用的是 “乘二取整,順序排列”,由於方法不同需要分開計算。下麵是16.125轉為二進位的例子:

16 / 2 = 8...0
 8 / 2 = 4...0
 4 / 2 = 2...0
 2 / 2 = 1...0
 1 / 2 = 0...1

0.125 * 2 = 0.25
0.25 * 2  = 0.5
0.5  * 2  = 1

10000.001

將小數相乘的結果,取結果的整數順序排列,得出小數位的二進位表示

二進位轉十進位

根據 “逢二進一 ” 的法則進行計數時,每兩個相同的單位組成一個和它相鄰的較高的單位,這種計數法叫做二進位計數 法,簡稱二進位。用二進位計數時,只需用兩個獨立的符號“0”和“1” 來表示。

整數

整數使用 “按權相加” 法,即二進位數首先寫成加權繫數展開式,然後按十進位加法規則求和。下麵是101010轉換位十進位的例子:

2^5 2^4 2^3 2^2 2^1 2^0   
 1   0   1   0   1   0
------------------------
32 + 0 + 8 + 0 + 2 + 0 = 42

上面從右數依次是2的0次方,2的1次方,2的2次方... , 只取位數為1的結果,將它們相加就可以得到十進位。

小數

10110.11轉十進位:

2^4 2^3 2^2 2^1 2^0 2^-1 2^-2
 1   0   1   1   0 .  1   1
-------------------------------
16 + 0 + 4 + 2 + 0 + 0.5 + 0.25 = 22.75

按位操作符

按位操作符(Bitwise operators) 將其操作數(operands)當作32位的比特序列(由0和1組成),前 31 位表示整數的數值,第 32 位表示整數的符號,0 表示正數,1 表示負數。例如,十進位數18,用二進位表示則為10010。按位操作符操作數字的二進位形式,但是返回值依然是標準的JavaScript數值。

按位與( AND)

對於每一個比特位,只有兩個操作數相應的比特位都是1時,結果才為1,否則為0。

用法: a & b

     9 (base 10) = 00000000000000000000000000001001 (base 2)
    14 (base 10) = 00000000000000000000000000001110 (base 2)
                   --------------------------------
14 & 9 (base 10) = 00000000000000000000000000001000 (base 2) = 8 (base 10)

在判斷一個數字奇偶時,可以使用 a & 1

function assert(n) {
    return n & 1 ? "奇數" : "偶數"
}
assert(3) // 奇數

因為奇數的二進位最後一位是1,而1的二進位最後一位也是1,通過 & 操作符得出結果為1

按位或(OR)

對於每一個比特位,當兩個操作數相應的比特位至少有一個1時,結果為1,否則為0。

用法: a | b

     9 (base 10) = 00000000000000000000000000001001 (base 2)
    14 (base 10) = 00000000000000000000000000001110 (base 2)
                   --------------------------------
14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10)

將浮點數向下取整轉為整數,可以使用 a | 0

12.1 | 0 // 12
12.9 | 0 // 12

按位異或(XOR)

對於每一個比特位,當兩個操作數相應的比特位有且只有一個1時,結果為1,否則為0。

用法: a ^ b

     9 (base 10) = 00000000000000000000000000001001 (base 2)
    14 (base 10) = 00000000000000000000000000001110 (base 2)
                   --------------------------------
14 ^ 9 (base 10) = 00000000000000000000000000000111 (base 2) = 7 (base 10)

按位非(NOT)

反轉操作數的比特位,即0變成1,1變成0。

用法: ~ a

 9 (base 10) = 00000000000000000000000000001001 (base 2)
               --------------------------------
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)

通過兩次反轉操作,可將浮點數向下取整轉為整數

~~16.125 // 16
~~16.725 // 16

左移(Left shift)

將 a 的二進位形式向左移 b (< 32) 比特位,右邊用0填充。

用法: a << b

     9 (base 10): 00000000000000000000000000001001 (base 2)
                  --------------------------------
9 << 2 (base 10): 00000000000000000000000000100100 (base 2) = 36 (base 10)

左移一位相當於在原數字基礎上乘2,利用這一特點,實現2的n次方:

function power(n) {
    return 1 << n
}
power(3) // 8

有符號右移

將 a 的二進位表示向右移 b (< 32) 位,丟棄被移出的位。

用法: a >> b

     9 (base 10): 00000000000000000000000000001001 (base 2)
                  --------------------------------
9 >> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

相比之下, -9 >> 2 得到 -3,因為符號被保留了。

     -9 (base 10): 11111111111111111111111111110111 (base 2)
                   --------------------------------
-9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)

與左移相反,右移一位在原數字基礎上除以2

64 >> 1 // 32

無符號右移

將 a 的二進位表示向右移 b (< 32) 位,丟棄被移出的位,並使用 0 在左側填充。

用法: a >>> b

在非負數來說, 9 >>>29 >> 2 都是一樣的結果

      9 (base 10): 00000000000000000000000000001001 (base 2)
                   --------------------------------
9 >>> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

而對於負數來說,結果就大有不同了,因為 >>> 不保留符號,當負數無符號右移時,會使用0填充

      -9 (base 10): 11111111111111111111111111110111 (base 2)
                    --------------------------------
-9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)

可以使用無符號右移來判斷一個數的正負

function isPos(n) {
    return (n === (n >>> 0)) ? true : false;
}

isPos(-1); // false
isPos(1); // true

雖然 -1 >>> 0 不會發生右移,但 -1 的二進位碼已經變成了正數的二進位碼, -1 >>> 0 結果為4294967295

Javascript進位轉換

toString

toString 常用於將一個變數轉為字元串,或是判斷一個變數的類型,例如:

let arr = []
Object.prototype.toString.call(arr) // [object Array]

你應該沒想過 toString 可以用於進位轉換,請看下麵例子:

(18).toString(2)  // 10010(base 2)
(18).toString(8)  // 22 (base 8)
(18).toString(16) // 12 (base 16)

參數規定表示數字的基數,是 2 ~ 36 之間的整數,若省略該參數,則使用基數 10。該參數可以理解為轉換後的進位表示。

parseInt

parseInt 常用於數字取整,它同樣可以傳入參數用於進位轉換,請看下麵例子:

parseInt(10010, 2) // 18 (base 10)
parseInt(22, 8)    // 18 (base 10)
parseInt(12, 16)   // 18 (base 10)

第二個參數表示要解析的數字的基數,該值介於 2 ~ 36 之間。如果省略該參數或其值為 0,則數字將以 10 為基礎來解析。如果該參數小於 2 或者大於 36,則 parseInt 將返回 NaN。

記得有道面試題是這樣的:

// 問:返回的結果
[1, 2, 3].map(paseInt)

接下來,我們來一步一步的看下過程發生了什麼?

parseInt(1, 0) // 基數為 0 時,以 10 為基數進行解析,結果為 1
parseInt(2, 1) // 基數不符合 2 ~ 36 的範圍,結果為 NaN
parseInt(3, 2) // 這裡以 2 為基數進行解析,但 3 很明顯不是一個二進位表示,故結果為 NaN

//題目結果為
[1, NaN, NaN]

手動實現進位轉換

雖然 JavaScript 為我們內置了進位轉換的函數,但手動實現進位轉換有利於我們理解過程,提高邏輯能力。對於初學者來說也是一個很不錯的練習例子。以下只簡單實現非負整數的轉換。

十進位轉二進位

基於 “除二取餘” 思路實現

function toBinary(value) {
    if (isNaN(Number(value))) {
        throw `${value} is not a number` 
    }
    let bits = []
    while (value >= 1) {
        bits.unshift(value % 2)
        value = Math.floor(value / 2)
    }
    return bits.join('')
}

使用

toBinary(36) // 100100
toBinary(12) // 1100

二進位轉十進位

基於 “按權相加” 思路實現

function toDecimal(value) {
    let bits = value.toString().split('')
    let res = 0
    while (bits.length) {
        let bit = bits.shift()
        if (bit == 1) {
            // ** 為冪運算符,如:2**3 為 8
            res += 2 ** bits.length
        }
    }
    return res
}

使用

toDecimal(10011) // 19
toDecimal(11111) // 33

寫在最後

本文為大家介紹了進位和位運算的相關知識,旨在溫故知新。我們只需要大概瞭解就好,因為在開發中真的用得少,至少我只用過 ~~ 來取整。而類似於~~這種取整操作還是儘量少用為好,對於其他開發者來說,可能會影響到代碼可讀性。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 滾動條常見樣式展示 overflow-x: hidden;/*是否對內容的左/右邊緣進行裁剪*/overflow-y: hidden;/*是否對內容的上/下邊緣進行裁剪*/overflow:scroll;/*左右滾動*/overflow: hidden;/*截取*/overflow: auto;/*... ...
  • 對象對於JavaScript至關重要,在ES6中對象又加了很多新特性。 對象字面量:屬性的簡潔表示法 ES6允許對象的屬性直接寫變數,這時候屬性名是變數名,屬性值是變數值。 let attr1 = "ES6"; let attr2 = 'testDemo'; let testObj = {attr1 ...
  • 有關浮動和清浮動問題,個人理解是float:left或者float:right的css樣式打破div標準流獨占一行的傳統,脫離了文檔流,所造成的浮動頁面影響類似"捆橡皮筋,當你把橡皮都拿走了,橡皮筋就回縮了",這時候,你要做的就是考慮如何有效的防止橡皮筋回縮,就是防止我們佈局的div盒子回縮,那清浮... ...
  • 如何通過absoulue與relative配合把一個盒子或者是把2個div塊同時放到頁面中央部分?定位完成後為什麼又需要margin-left與margin-top各往回走50%的長度,別忘記用z-index定位高度,請看下麵代碼展示: ...
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <button class="btn">按鈕</button> <script src="../js/j ...
  • 用 showhide 改寫dropdown 模塊: 1.首先在 css中新增動畫相關樣式 /*showhide組件的樣式*/ .fadeOut{ opacity: 0; visibility: hidden; } /*收縮樣式*/ .slideUpDownCollapse{ height:0 !im ...
  • table表格中border-collapse: collapse;/*表格邊框是否合併*/border-spacing: 10px;/*表格邊框之間的距離*/定位詳情可以閱讀position屬性值4缺一帶你瞭解相對還是絕對抑或是固定定位,實現div絕對居中法/*父定位子絕對,子的坐標系是父的左上角... ...
  • 滑鼠cursor常見樣式crosshair;/*十字形狀*/cursor:pointer;/*小手形狀*/cursor:wait;/*等待形狀*/cursor:text;/*預設 文本形狀*/cursor:default;/*箭頭指示形狀*/cursor:help;/*幫助形狀*/ 列表(list... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...