數字系統並沒有你想的那麼複雜

前言

今天要談的主題是「數字系統」

數字系統在我們的生活或許不怎麼起眼,但如果是在電腦科學這個領域,就很難不談到它了。
不知道各位會不會跟我一樣,一直對於數字系統有點似懂非懂的感覺,或者是需要用到時就滿頭霧水。
基於這個原因,所以我決定寫一篇文章來記錄,希望跟我有一樣這種困擾的各位能夠好好紮實地把這些重要知識給學起來!

學習目標

  1. 了解數字系統(知道什麼是二進位、八進位、十進位、十六進位)
  2. 知道怎麼把轉換進位制(例如:十進位轉成二進位)
  3. 知道怎麼寫出一個能夠轉換進位制的程式碼

正文

認識數字系統

在學怎麼對數字做轉換前,當然要先知道什麼叫數字系統,所以這裡會先簡單介紹一下關於數字系統的知識。

數字系統可以分為:

  • 二進位(Binary)
  • 八進位(Octal)
  • 十進位(Decimal)
  • 十六進位(Hexadecimal)

先從我們生活中最熟悉的的十進位來做說明吧。(我們現在正在使用的數字系統就是十進位)

題外話:為什麼我們的數字系統是 10 進位?

也許是因為我們人只有 10 根手指頭吧…

如果你對於「進位」這個詞感到很害怕或陌生的話,別擔心。

其實講的白話一點,這只是用來代表 「你要用哪個規則來表示一個數」 的意思。

而且你早就學會怎麼做進位這件事了(待會就知道了)

不知道各位有沒有上過計算機概論或者自己 Google 過,大部分應該會得到這樣的解釋:

「逢 10 進位」(如果是十進位的話)

以前的我聽到這個解釋後,我心裡的感想是,痾…到底什麼叫做逢 10 進位?

不過在我理解後,我認為這句話的完整意思應該要這樣說:「每當碰到 10 這個數字,就增加一個位數」

讓我們直接來看個例子吧。

如果要你算 18 + 25,你會怎麼計算呢?(我知道你會馬上說是 43,但重點是你怎麼算的?)

我相信不管你是數學菜逼還是數學天才,應該都是用這種方式來計算的。

  1. 先計算8 + 5的部分,會得到13
  2. 接著因為13超過 10 了,所以把1加到下一個位數,留下3
  3. 接著計算1 + 2的部分,會得到3
  4. 接著因為前面的1要加到這個位數,所以最後3要再加上這個被進位的1,得到4
  5. 最後才能得到答案43

不知道你有沒有注意到?

在第二個步驟的時候,你很自然的做了進位這件事,你知道 13 是一個超出 10 的數字,所以就把 1 放到十位數去,讓個位數只剩下 3。

沒錯,逢 10 進位就是指這個很簡單的動作而已。

如果你還是似懂非懂的話,你可以再思考看看,如果你不做進位這個動作的話,會變怎麼樣?

  1. 先計算8 + 5的部分,會得到13
  2. 接著計算1 + 2的部分,會得到3
  3. 最後得到313

這時候你應該就能理解,為什麼需要進位這件事了吧?

如果沒有進位的話,那數字會變得非常的長,你也很難理解這個數實際要表達的是什麼。

所以再強調一次,數字系統的用途只是讓你更好地去 「表示一個數」,僅此而已。

到這邊你都能理解的話,那接著要理解其他進位制就不是什麼難事了,只是換一個規則來表示而已。

來看一些例子吧

現在我們有一個 10 進位的數字3,現在我們要改成用 2 進位來表示的話,怎麼表示?

首先,既然是二進位,所以我們的規則就會變成是「逢 2 進位」。

  1. 3是一個超過 2 的數字,所以把1加到下一個位數,留下1
  2. 1沒有超過 2,所以不用再進位
  3. 最後得到11

再來一個,4的話呢?

  1. 4是一個超過 2 的數字,所以把1加到下一個位數,留下2
  2. 2還是一個超過 2 的數字,所以再把1加到下一個位數,留下0
  3. 2(前面進位的兩個 1),是一個超過 2 的數字,所以把1加到下一個位數,留下0
  4. 1沒有超過 2,所以不用再進位
  5. 最後得到100

以上大致就是數字系統的核心概念了,只要你能理解,那就算你想發明一個 87 進位也應該不會是個問題….

這邊特別補充一下,有些人可能會想問?十六進位的話10 ~ 11要怎麼表示?

這個疑惑很合理,畢竟我們直接用 11 ~ 15 來表示一個位數的話顯然是有點難理解。

所以為了避免這個問題,會改用這樣來表示:

  • a 代表 10
  • b 代表 11
  • c 代表 12
  • d 代表 13
  • e 代表 14
  • f 代表 15

這裡提供一個進位轉換的網頁,如果還是不太清楚的話,可以到這裡去玩玩看,去觀察數字在進位時的變化,多試幾次就能幫助你去理解這個概念囉!

怎麼對數字做進位制轉換

在學怎麼轉換前,先解釋一下為什麼要學這個東西。

雖然現在隨便 Google 都有現成的工具可以幫你做進位轉換,但有些時候重要的並不只是數字轉換後的結果,而是它在轉換過程中的一些涵義。

試著去理解這些涵義,會對你在寫程式或思考的時候是有一些幫助存在的(相信我~)

把十進位轉換成其他進位

假設一個十進位的數字為25,接著來試著把它轉換成二進位

二進位

  • 25 / 2 = 12 … 1
  • 12 / 2 = 6 … 0
  • 6 / 2 = 3 … 0
  • 3 / 2 = 1 … 1
  • 1 / 2 = 0 … 1

接著再把這些數字由下至上組合起來,11001就是 25 的 2 進位表示法。

你應該注意到了,我們其實就只是一直在做,除以 2 後得到的餘數而已,所以你也能把他稱作取餘數大法(?

所以只要你知道怎麼取餘數,那你就會做進位制的轉換了。

不過在這裡先聲明,雖然你可以用死記的方式來做轉換,但比起用死記的,我更推薦你去理解背後的涵義。

只要你仔細去觀察每個步驟,就會發現它其實並不複雜,都是前面所說的基本概念而已。

所以我們先看到第一個步驟。

  1. 對 25 除以 2,得到商為12,餘數為1

這裡你先思考看看,為什麼我們要對 25 做除以 2,跟取它的餘數這件事?(回想看看我們介紹數字系統時的概念)

因為 25 是一個超過 2 的數嘛!所以要做什麼?進位阿!阿要進位幾次?進位數字到不超過 2為止嘛!

那我要怎麼知道該進位幾次,跟什麼時時候數字才會不超過 2 這件事?

透過第一步所做的事情就能知道囉!

把某個數字對 2 做除法,求出它的商跟餘數,商數代表這個數字進位了幾次,餘數就代表剩下了多少數

一直重複這個步驟,直到商數為 0,就代表不能再進位了,而此時的餘數就代表進位到最後剩下的數

所以我們在重新看一下前面的計算,可以列成以下這些步驟:

  • 25 / 2 = 12 … 1,代表 25 可以被 2 進位12次,剩下1,進位後的 12 還可以被 2 進位幾次?
  • 12 / 2 = 6 … 0,代表 12 可以被 2 進位6次,剩下0,進位後的 6 還可以被 2 進位幾次?
  • 6 / 2 = 3 … 0,代表 6 可以被 2 進位3次,剩下0,進位後的 3 還可以被 2 進位幾次?
  • 3 / 2 = 1 … 1,代表 3 可以被 2 進位1次,剩下1,進位後的 1 還可以被 2 進位幾次?
  • 1 / 2 = 0 … 1, 代表 1 不能再被 2 進位了,最後剩下的數為1

不管是二進位、八進位、十六進位,甚至是十進位本身,都可以遵循這個規則去做。

接著試著自己練習看看吧!把 25 轉換成其他進位看看,如果都正確的話,就代表你有理解這個概念囉!

把其他進位轉換成十進位

延續前面的例子,現在我們知道11001是代表 25,但這之間是發生了什麼?怎麼做到的?

其實你只要把她拆成次方來看就可以了,像這樣:

1 x 24 + 1 x 23 + 0 x 22 + 0 x 21 + 1 x 20

把上面這些算式算出來後,就會得到25

傑克,這真是太神奇了!!

為什麼能這樣呢?

我個人認為比較好理解的方式是,用位數的概念來觀察。

譬如說,如果是要你把 10 進位用次方來表示的話,你應該能很直覺的得出以下式子:

25 = 2 x 101 + 5 x 100,得到25

為什麼這麼直覺?

  1. 首先你知道,10 進位代表每個位數的數字只能在 0 ~ 9

  2. 接著你又知道第一個位數的範圍必須是在 0 ~ 9 之間的數,那一定得是1 x n這樣的算式才有辦法求出,所以如果要寫成次方的話,我們只能寫成 100,接著在把 100去乘上一個數,就能得出 0~9 之間的數字。

  3. 接著是第二個位數,代表數字的範圍必須在 10 ~ 99 之間,那就一定得是10 x n這樣的算式才有辦法求出,所以寫成次方的話就會是 101,接著再把 101去乘上一個數,就能得出 10~99 之間的數字。

  4. 最後把兩個數字相加,就能得出最後的結果,也就是25

其實換成 2 進位也是一樣的道理:

  1. 首先你知道,2 進位代表每個位數的數字只能在 0 ~ 1
  2. 現在第一個位數的範圍是在 0 ~ 1,那得是1 x n,所以就會是 20
  3. 第二個位數的範圍是在 2 ~ 4,那得是 2 x n,所以就會是 21
  4. 第三個位數的範圍是在 4 ~ 8,那得是4 x n,所以就會是 22
  5. 以此類推

發現到規律了嗎?每當我們進一個位數,就代表範圍會增加一倍,所以次方的數字就得跟著加 1。

所以再回過頭來看11001

照著前面的邏輯,你腦中應該要有這個畫面:

1 1 0 0 1
1 x 24 1 x 23 0 x 22 0 x 21 1 x 20

接下來該怎麼變成 10 進位應該就不用我多解釋了吧?

實做一個轉換進位的程式

這裡就留給各位去挑戰看看,如果感到苦惱的話就先思考看看自己是不是有什麼地方沒有弄清楚?

另外關於 16 進位,因為要考慮到 10 ~ 15 的問題,所以這部分如果覺得比較複雜的人,可以先省略 16 進位,先從二、八進位試試看!

附上自己的程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function covert(n, base) {
// 儲存轉換後的結果(用三元運算子設定初始值)
let result = base !== 16 ? 0 : ''
// 代表位數
let digit = 0

while (n !== 0) {
// 餘數
let remainder = n % base

// 16進位的餘數處理
if (remainder === 10) remainder = 'A'
if (remainder === 11) remainder = 'B'
if (remainder === 12) remainder = 'C'
if (remainder === 13) remainder = 'D'
if (remainder === 14) remainder = 'E'
if (remainder === 15) remainder = 'F'

// 非16進位的表示法
if (base !== 16) {
// 取出餘數並乘上對應位數
result += remainder * 10 ** digit
// 更新為下個位數
digit++
// 取出進位數
n = Math.floor(n / base)
} else {
result = remainder + result
// 取出進位數
n = Math.floor(n / base)
}
}
return result
}

console.log(covert(8, 2)) // 1000
console.log(covert(26, 16)) // 1A

文末

謝謝看完這篇文章的各位,自己開始寫文章後才明白,寫文章不是件想像中容易的事,不知不覺中一個下午就消失了。不過在完成這篇文章後,我也感受到其實寫文章對於學習確實是有幫助的,在撰寫的過程中也能發現一些自己的問題。

像是很多時候我們以為自己了解某個東西,但實際上並不是這個樣子,事實上我們並沒有真正的理解,只是誤以為自己好像理解這件事,所以我們才更需要去正視自己的問題,找出改善方法,或者弄清楚是卡住的哪個點?這樣子可能才能真正的去學好一個知識吧?我是這樣子認為的。

最後還是再次感謝各位,如果這篇文章幫你解開了你多年的困擾的話,那就再好不過了!
當然,如果文中有任何錯誤,或是你認為有更好的建議的話,歡迎向我聯絡。

參考資料

二、八、十與十六進位 (數字系統) 轉換教學
免費線上單位換算
數字系統 - NUTNCSIE10412

which?that?關係子句?
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×