第6天筆記

進制基本概念

本小節知識點:

  1. 【瞭解】什麼是進制?
  2. 【理解】常見的進制
  3. 【瞭解】編程輸出各種進制

1.什麼是進制?

  • 是一種計數的方式,數值的表示形式

2.常見的進制

  • 十進制、二進制、八進制、十六進制

3.進制數字進位方法

  • 十進制 0、1、2、3、4、5、6、7、8、9 逢十進一

  • 二進制 0、1 逢二進一

    • 書寫形式:需要以0b或者0B開頭,比如0b101
  • 八進制 0、1、2、3、4、5、6、7 逢八進一

    • 書寫形式:在前面加個0,比如045
  • 十六進制 0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F 逢十六進一

    • 16進制就是逢16進1,但我們只有0~9這十個數字,所以我們用A,B,C,D,E,F這五個字母來分 別表示10,11,12,13,14,15。字母不區分大小寫。
    • 書寫形式:在前面加個0x或者0X,比如0x45
  • 數一下方塊的個數, 並用十進制,二進制,八進制,十六進制表示 

  • 練習

    1.判斷下列數字是否合理
    00011  0x001  0x7h4  10.98  0986  .089-109
    +178  0b325  0b0010  0xffdc 96f 96.0f 96.oF  -.003
    

4.編程輸出各種進制

  • 假設有整型變量a,初始值爲13,打印其8進制、16進制測試
    int a = 13;
    printf("10->8: %o\n", a);
    printf("10->16: %x\n", a);
    
  • 定義一個二進制數、八進制數、十六進制,打印其對應的10 進制
int a = 0b00000000000000000000000000001101;
printf("2->10: %d\n", a);

a = 015;
printf("8->10: %d\n", a);

a = 0xd;
printf("16->10: %d\n", a);

輸出結果:
2->10: 13
8->10: 13
16->10: 13

進制轉換

本小節知識點:

  1. 【掌握】10 進制轉 2 進制
  2. 【掌握】2 進制轉 10 進制
  3. 【掌握】2 進制轉 8 進制
  4. 【掌握】8 進制轉 2 進制
  5. 【掌握】2 進制轉 16 進制
  6. 【掌握】16 進制轉 2 進制

1.10 進制轉 2 進制

  • 方法:

    • 除2取餘, 餘數倒序得到的序列就是二進制表示形式
  • 例如:將十進制(97) 10轉換爲二進制數 


2.2 進制轉 10 進制

  • 方法:
    • 每一位二進制進制位的值 * 2的(當前二進制進制位索引)
      • 索引從0開始, 從右至左
    • 將所有位求出的值相加

例如: 二進制11轉換爲10進制
0b1011 = 1 * 2^0 + 1 * 2^1 + 0 * 2^2 + 1 * 2^3
       = 1 * 1 + 1 * 2 + 0 * 4 + 1 * 8
       = 1 + 2 + 0 + 8
       = 11

3.2 進制轉 8 進制

  • 三個二進制位代表一個八進制位, 因爲3個二進制位的最大值是7,而八進制是逢八進一

0b11110011 = 0b 011 110 011
           = 0363

4.8 進制轉 2 進制

  • 方法:
    • 每一位八進制位的值 * 8的(當前二進制進制位索引)
      • 索引從0開始, 從右至左
    • 將所有位求出的值相加

027 = 7 * 8^0 + 2 * 8^1
    = 7 * 1 + 2 * 8
    = 23

3.2 進制轉 16 進制

  • 四個二進制位代表一個十六進制位,因爲4個二進制位的最大值是15,而十六進制是逢十六進一

例如: 二進制243轉換爲16進制
0b11110011 = 0b 1111 0011
           = 0xF3

4.16 進制轉 2 進制

  • 將16進制的每一位拆成4爲二進制位
例如:
0x25 =0b 0010 0101
     =0b100101

機器數和真值的概念

原碼反碼補碼概念及轉換

本小節知識點:

  1. 【理解】原碼反碼補碼基本概念
  2. 【理解】-1在內存中存儲細節
  3. 【理解】練習

1.原碼反碼補碼基本概念

  • 數據在計算機內部是以補碼的形式儲存的
  • 數據分爲有符號數和無符號數

    • 無符號數都爲正數,由十進制直接轉換到二進制直接存儲(其實也是該十進制的補碼)即可。 有符號數用在計算機內部是以補碼的形式儲存的。( 正數的最高位是符號位0,負數的最高位是 符號位1。 對於正數:反碼==補碼==原碼。 對於負數:反碼==除符號位以外的各位取反。補碼=反 碼+1)
    • 正數的首位地址爲0,其源碼是由十進制數轉換到的二進制數字
    • 負數的首位地址爲1,其源碼後面的位也爲10進制數轉換過去的二進制數字,都是用補碼方式表示 有符號數的。
  • 在探求爲何機器要使用補碼之前, 讓我們先了解原碼, 反碼和補碼的概念.對於一個數, 計算機要 使用一定的編碼方式進行存儲. 原碼, 反碼, 補碼是機器存儲一個具體數字的編碼方式. 原碼, 反碼, 補碼是計算機原理的術語。說白了就是爲了理解計算機2進制用的。對於C/C++來 說,是和數據類型有關的。

  • 原碼

    • 原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其餘位表示值
      原碼:[+1]0000 0001
      原碼:[-1]1000 0001
      
  • 反碼

    • 正數的反碼是其本身
    • 負數的反碼是在其原碼的基礎上, 符號位不變,其餘各個位取反.
      原碼:[+1]0000 0001 反碼:0000 0001
      原碼:[-1]1000 0001 反碼:1111 1110
      
      • 可見如果一個反碼錶示的是負數, 人腦無法直觀的看出來它的數值. 通常要將其轉換成原碼再計 算.
  • 補碼
  • 正數的補碼就是其本身
  • 負數的補碼是在其原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1. (即在反碼的基礎上+1)
    原碼:[+1]0000 0001 反碼:0000 0001 補碼:0000 0001
    原碼:[-1]1000 0001 反碼:1111 1110 補碼:1111 1111
    
    • 對於負數, 補碼錶示方式也是人腦無法直觀看出其數值的. 通常也需要轉換成原碼在計算其數值.

2.-1在內存中存儲細節

  • 在64爲計算機中,-1的原碼、反碼、補碼如下
    -1原碼 1000 0000 0000 0000 0000 0000 0000 0001
    -1反碼 1111 1111 1111 1111 1111 1111 1111 1110
    -1補碼 1111 1111 1111 1111 1111 1111 1111 1111
    
    • 正整數取反+1就是對應負數

3.練習

  • 計算分別寫出-13的原碼、反碼、補碼
    -13原碼:10000000 00000000 00000000 00001101
    -13反碼:11111111 11111111 11111111 11110010
    -13補碼:11111111 11111111 11111111 11110011

原碼反碼補碼練習

本小節知識點:

  1. 【掌握】爲什麼要引入反碼和補碼?
  2. 【瞭解】補碼的再深入

1.爲什麼要引入反碼和補碼?

  • 在開始深入學習前, 我的學習建議是先"死記硬背"上面的原碼, 反碼和補碼的表示方式以及計算方法.

  • 現在我們知道了計算機可以有三種編碼方式表示一個數. 對於正數因爲三種編碼方式的結果都相同, 所以不需要過多解釋

原碼:[+1]0000 0001
反碼:[+1]0000 0001
補碼:[+1]0000 0001
  • 但是對於負數, 可見原碼, 反碼和補碼是完全不同的. 既然原碼纔是被人腦直接識別並用於計算表示方式, 爲何 還會有反碼和補碼呢?
    原碼:[-1]1000 0001
    反碼:[-1]1111 1110
    補碼:[-1]1111 1111
    
    • 首先, 因爲人腦可以知道第一位是符號位, 在計算的時候我們會根據符號位, 選擇對真值區域的 加減. (真值的概念在本文最開頭). 但是對於計算機, 加減乘數已經是最基礎的運算, 要設計的 儘量簡單. 計算機辨別"符號位"顯然會讓計算機的基礎電路設計變得十分複雜! 於是人們想出了 將符號位也參與運算的方法. 我們知道, 根據運算法則減去一個正數等於加上一個負數, 即: 1-1 = 1 + (-1) = 0 , 所以機器可以只有加法而沒有減法, 這樣計算機運算的設計就更簡單了.

2.補碼的再深入

  • 計算十進制的表達式: 1-1=0

    1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
    
    • 如果用原碼錶示, 讓符號位也參與計算, 顯然對於減法來說, 結果是不正確的.這也就是爲何計算 機內部不使用原碼錶示一個數.
  • 爲了解決原碼做減法的問題, 出現了反碼:

    1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原
                   = [0000 0001]反 + [1111 1110]反
                   = [1111 1111]反
                   = [1000 0000]原 (1111 1111,符號位不變,其他爲逐位取反)
                   = -0
    
    • 發現用反碼計算減法, 結果的真值部分是正確的. 而唯一的問題其實就出現在"0"這個特殊的數值 上. 雖然人們理解上+0和-0是一樣的, 但是0帶符號是沒有任何意義的. 而且會有[0000 0000]原和 [1000 0000]原兩個編碼表示0.
  • 於是補碼的出現, 解決了0的符號以及兩個編碼的問題:

    1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原
                 = [0000 0001]補 + [1111 1111]補
                 = [0000 0000]補
                 = [0000 0000]原
    
    • 這樣0用[0000 0000]表示, 而以前出現問題的-0則不存在了.而且可以用[1000 0000]表示-128: (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]補 + [1000 0001]補 = [1000 0000]補
    • -1-127的結果應該是-128, 在用補碼運算的結果中, [1000 0000]補 就是-128. 但是注意因爲實際 上是使用以前的-0的補碼來表示-128, 所以-128並沒有原碼和反碼錶示.(對-128的補碼錶示[1000 0000]補算出來的原碼是[0000 0000]原, 這是不正確的)
  • 單字節的表示的最大的負數是多少? ``` [10000000]補 =[10000000]反+1 =11111111+1 =(1)00000000 =00000000(最高位溢出了,符號位變成了0)

有人會問 10000000這個補碼錶示的哪個數的補碼呢? 其實這是一個規定,這個數表示的是-128 所以n位補碼能表示的範圍是 -2^(n-1)到2^(n-1)-1 比n位原碼能表示的數多一個

- 所以得出整型數的數值範圍:
int number1 = 0b10000000000000000000000000000000;
int number2 = 0b01111111111111111111111111111111;
int number3 = 0b11111111111111111111111111111111;
printf("number1 = %d\n", number1);
printf("number2 = %d\n", number2);
printf("number3 = %d\n", number3);

輸出結果: number1 = -2147483648 number2 = 2147483647 number3 = -1

```

位運算符介紹(一)

1.本小節知識點:

  1. 【掌握】什麼是位運算符?
  2. 【掌握】位運算符與
  3. 【掌握】位運算符或
  4. 【掌握】位運算符異或
  5. 【掌握】位運算符取反
  6. 【掌握】練習

1.什麼是位運算符?

  • 位運算是指按二進制進行的運算。在系統軟件中,常常需要處理二進制位的問題。 C語言
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章