生活中的 Computer Science

 

 

Lesson 1: 我的錢怎麼變成負的?

電腦中的資料儲存與表示方法

先讓大家看一則慘絕人寰的案例

[超幹] 大富翁我X你娘!!!
我好不容易冷靜下來

事情是這麼開始的,我玩了手機版的大富翁4fun
玩著玩著把錢夫人幹掉,金貝貝住進了醫院之後身上只剩500塊
我踩到大財神,和所有對手收2600元
正當我認為贏的那一刻我發現一件很奇怪的事情

金貝貝身上有21億!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我X你媽的金貝貝身上有21億啊!!!!!!!!!!!!!
X你娘我看了我數了兩次是真的他媽的21億!!!
X你娘我身上一百多萬我以為我超強超威

X你媽的金貝貝從街頭魯蛇突然變成三代公務員我操!!!!

疑問:

 

500 - 2600 = 21億

為什麼?

先從進制開始談起吧

十進位(Decimal)

我們日常生活中所使用的進位系統,相傳是因為有十根手指頭

 

來開始數數吧!

1, 2, 3, 4, 5, 6, 7, 8, 9,10

11, 12, 13, 14, ....19, 20

數字裡面不會有「十」,9的下一個其實是「一零」

碰到「十」就要進位

 

八進位(Octal)

章魚所使用的進位系統

 

來開始數數吧!

1, 2, 3, 4, 5, 6, 7, 10, 11, 12, ...17, 20

數字裡面不會有「8」,7的下一個是「一零」,代表進位

 

十六進位(Hexadecimal)

來開始數數吧!

1, 2, 3, 4, 5, 6, 7, 8, 9, 

9的下一個怎麼辦呢?不能用「10」,因為這是兩個位數

 

沒關係!我們有英文字母

9, A(10), B(11), C(12), D(13), E(14), F(15)

10, 11, 12, ...1A, 1B, ..1F, 20

 

小知識 #1

大家有看過所謂的「色碼」嗎?

就是用一組東西來表示顏色,例如說白色就是#FFFFFF

黑色就是#000000,紅色就是#FF0000

其實這就是十六進位表示法

 

在電腦裡面的三原色是:紅(Red)、綠(Green)、藍(Blue)

每個顏色又細分成256個數值

紅色256, 綠色256, 藍色0,那就是紅色+綠色,也就是黃色

而256的十六進位表示法,正好是FF

所以#FFFF00就是FF(R), FF(G), 00(B)就是黃色的色碼囉

小知識 #2

十進位的縮寫是Dec,八進位是Oct

有沒有發現有點眼熟?

 

十二月是December,十月是October,難道有什麼關係嗎?

其實原本十月叫做December,八月叫做October

 

原本古羅馬曆法只有十個月,後來決定新增兩個月到年尾

之後又決定把那兩個月放到最前面,就成了現在的一二月

原先的月份順著往後移兩個月,於是October就從八月變作十月

December也從十月變作十二月了

二進位(Binary)

電腦中最基本的數值表示方法

又或者以電路的角度來看,0即是關,1即是開

 

一樣來數數吧!

0, 1, 10, 11, 100, 101, 110...

不會有2出現,因為只要碰到2就要進位,跟之前的原理都一樣

 

複習

二進位 1010 1000
八進位 12 10
十進位 10 8
十六進位 A 8

用數學的角度

23(Dec) = 2*10^1 + 3*10^0 = 23(Dec)
23(Dec)=2101+3100=23(Dec)23(Dec) = 2*10^1 + 3*10^0 = 23(Dec)
23(Oct) = 2* 8^1 + 3* 8^0 = 19(Dec)
23(Oct)=281+380=19(Dec)23(Oct) = 2* 8^1 + 3* 8^0 = 19(Dec)
23(Hex) = 2*16^1 + 3*16^0 = 35(Dec)
23(Hex)=2161+3160=35(Dec)23(Hex) = 2*16^1 + 3*16^0 = 35(Dec)
1010 = 1*2^3+0*2^2+1*2^1+0*2^0 = 10
1010=123+022+121+020=101010 = 1*2^3+0*2^2+1*2^1+0*2^0 = 10
1010 = 2^3+2^1 = 10
1010=23+21=101010 = 2^3+2^1 = 10

小測試

 

這個世界有10種人

一種是懂二進位的

另外一種是不懂二進位的

資料儲存

Bit

資料儲存的最小單位,只能儲存1或0

比特幣(Bitcoin)的比特就是在指這個

 

Byte

8個位元就是1個Byte,8 bit = 1 byte

所以Byte又稱:位元組

Kilobyte

其實就是Kilo+byte,Kilo就是1000的意思

像是Kilogram = Kilo+gram = 1000公克


兩種標準:

1KiB = 1024 bytes

1kB = 1000 bytes 


Megabyte

其實就是Mega+byte,Mega就是百萬的意思

 

兩種標準:

1Mib = 1024 Kb = 1024*1024 bytes

1MB = 1000 Kb = 1000*1000 bytes 

 

變形金剛裡的密卡登(Megatron)
電影麥克邁:超能壞蛋(Megamind)
兆豐國際商業銀行(Megabank)
(中國把Mega稱做兆)

Gigabyte

其實就是Giga+byte

 

兩種標準:

1Gib = 1024 Mib = 1024*1024 Kib

1GB = 1000 Mb = 1000*1000 Kb  

 

1 Byte = 8 Bits 1 Kilobyte (KB) = 1024 Bytes
1 Megabyte (MB) = 1024 KB
1 Gigabyte (GB) = 1024 MB
1 Terabyte (TB) = 1024 GB
1 Petabyte (PB) = 1024 TB
1 Exabyte (EB) = 1024 PB
1 Zettabyte (ZB) = 1024 EB
1 Yottabyte (YB) = 1024 ZB

Google 的 MapReduce 每個月所要處理的資料量超過 400 PB
Facebook 註冊用戶超過 10 億,每天產生 300 TB 以上的資料量

 

來源:

http://buzzorange.com/techorange/2013/04/16/why-virtual-machine-is-so-attractive/

數字是怎麼儲存的?

通常數字是用32個bit儲存的

也就是4個bytes

 

還記得嗎?每個bit可以表示0或1

所以32個bit可以表示2^32種情形

 

2^32 = 42,9496,7296

大約是40億左右

 

咦,好像少了什麼?

 

負數怎麼辦呢?

方法一

既然負數跟正數差在符號,那就讓第一位表示符號就好啦!

 

假設現在數字都用8個位元來存

0000 1000 = 8

1000 1000 = -8

0001 0010 = 18

1001 0010 = -18

 

可是,這樣如果要做加法,要怎麼加?

方法二(一補數)

不然,我們把所有位元顛倒試試看!

 

假設現在數字都用8個位元來存

0000 1000 = 8

1111 0111 = -8

0001 0010 = 18

1110 1101 = -18

8+(-8) = 1111 1111

18+(-18) = 1111 1111

好像只差一步了

方法三(二補數)

把所有位元顛倒並且+1

 

假設現在數字都用8個位元來存

0000 1000 = 8

1111 1000 = -8

0001 0010 = 18

1110 1110 = -18

8+(-8) = 1 0000 0000

因為我們的數字是用八個位元來存,所以最左邊的1會被丟掉

就變成了0000 0000

以一個32bit的整數來說

表示範圍是 -2^31~2^31-1

也就是 -2147483648 ~ 2147483647 

 

如果不想要負數的話

也有一種資料型態是「無號整數」,所以若是32bit

就可以表示0~2^32-1

 

若是超出範圍怎麼辦?

假設現在是8位元無號整數(可表示0~255)

1100 1000 = 200
1100 1001 = 201
----------- 相加
1001 0001 = 145

奇怪,怎麼相加之後反而變小了?
因為200+201 = 401,超出了8位元可以表示的範圍

那如果是有號整數呢?(可表示-128~127)
0111 0000 = 112
0100 0000 = 64
---------- 相加
1011 0000 = 負的0101 0000 = -80
兩個正數之後相加居然變成負數!
因為相加之後超過可以表示的範圍
我們稱之為overflow(溢位)


揭開真相

 

最一開始看到的大富翁範例

原本錢是正的,減去一些數之後原本應該是負數

但因為莫名的bug,導致錢變成了很大的正數

 

於是我們可以猜測說

可能程式因為某些bug把錢用無號整數儲存

在小於0之後就變成了超大整數

那小數怎麼辦?

1/3 = 0.33333333....

電腦中的小數儲存有一定位數,所以不可能存的完全精準

儲存小數分成三個部分:符號,指數,小數

可以把每個數字都轉化成固定格式

例如說 0.00000853 = 0.853*10^(-5)

0.001234 = 0.1234*10^(-2)

你在這一堂課學到的東西:

 

1. 進制轉換(二進位、八進位、十進位、十六進位)
2. 資料單位(bit, byte, kb, mb, gb...)
3. 浮點數(簡單介紹浮點數儲存方式與浮點數會碰到的問題)
4. 補數(在電腦中儲存負數怎麼存?)
5. 資料型態(在程式語言中數字的儲存方式)

 


更詳細的浮點數講解:
http://blog.dcview.com/article.php?a=VmhQNVY%2BCzo%3D

Made with Slides.com