[C++, CPP 教學 教程 教材 Tutorial] 基本資料型態(Fundamental Data Type) - 算數型態(Arithmetic Type)
YehYeh\'s Notepad yehyeh@gmail.com 

[C++, CPP] 基本資料型態(Fundamental Data Type)

算術型態(Arithmetic Type)

  • 資料型態可以自行定義,也可以使用C++預設提供的幾種資料型態
  • 基本資料型態:C++預設提供的資料型態。
    算術型態
    (Arithmetic Type)
    整數 有號整數 signed char
    short
    int
    long
    無號整數 bool
    char
    wchar_t
    浮點數 float
    double
    long double
  • 數值範圍:這裡介紹的數值範圍會符合大部份系統
    • 有時因系統或硬體的關係,數值範圍可能會和這裡介紹的有所出入,確切的數值範圍應查看相關的標頭檔。
      • 例如PC上int是4byte,嵌入式系統上int可能是2byte
    • 整數型態的範圍:可參考climits標頭檔裡的定義
    • 浮點數型態的範圍及精確度:可參考float.hcfloatlimits標頭檔裡的定義
      • #include <limits>
      • 最大值:std::numberic_limits<型態>::max( );
      • 最小值:std::numberic_limits<型態>::min( );
      • 二進位的位數:std::numeric_limits<型態>::digits
        • 浮點數取出來為假數的二進位值位數
  • int整數,即沒有小數的數值
    • 一般32位元電腦int變數的大小為4bytes(32bits)
    • int的長度通常以硬體能最高速運算的長度決定
  • float浮點數,浮點數是有小數的數值
    • 電腦中記憶浮點數的方法是基值和倍數分開儲存,倍數值和小數點移動的位數有關,所以稱為浮點數
    • 電腦上使用的浮點數精確度有限,所以有些運算常發生錯誤
      • 很多10進位浮點數無法轉換成完全精確的2進位浮點數
        cout << 10.0/3.0 << endl;     //顯示3.33333	  
        
      • 用2個接近的值相減,可能會失去精確度
        cout << 3.33333 - 1.0/3.0 << endl;  //顯示-3.41733e-006	  
        
      • 處理大範圍的值可能會出現錯誤
        cout << 9000000.0f + 0.0000009 << endl; //顯示9e+006	  
        
  • NaN(Not a Number):表示非數學定義的結果,如除以0
  • +infinity(正無窮大):符號為+,假數bit皆為0,指數bit皆為1
  • -infinity(負無窮大):符號為-,假數bit皆為0,指數bit皆為1
運算 結果
±n/0 ±infinity
±infinity ± n ±infinity
±infinity * n ±infinity
±infinity / n ±infinity
0 / 0 NaN
±infinity / ±infinity NaN
infinity - infinity NaN
infinity * 0 NaN

魔術數字(Magic Number)

在程式碼中直接使用數字稱為魔術數字,讓人很難瞭解該數值的意義,時間一久可能連設計者也記不得。這種數字就像魔術一樣,讓人不清楚是怎麼變出來的。

    float priceWithTax = 1.03 * price;  // Magic Number = 1.03

1.03是什麼東西或由何而來,很不清楚,可以改寫成:

    float tax = 1.03;
    float priceWithTax = tax * price;
  • 精確度(Precision)
    • 指基值(假數)的有效位數,最後一位數有可能是四捨五入的結果
  • char:字元型態
    • 主要是用來儲存ASCII(American Standard Code for Information Interchange)字元,也可以儲存1byte的整數
    • 儲存ASCII字元時,需使用單引號括住
    • char letter1 = 'A';
      char letter2 = 65;
      char letter3 = 0x41;
      char letter4 = ++64;
      
    • char可能是有號,也有可能是無號,即儲存的範圍可能是(0~255)也可能是(-128~127)
    • char是否有號,由編譯器的開發廠商決定
    • 要測試char是否有號,可指派一個負數給char變數,再將char變數轉為整數印出,若可正確印出負數,即為有號
    • 測試char是否有正負號?
      char c = -125;
      cout << (int) c << endl;	//顯示-125即為有號,顯示131即為無號
      
  • bool:布林型態,記錄真(true)或假(false)
    • bool型態的大小為1byte,所以也可以儲存0 ~ 255的整數
    • 舊的C++程式會使用0代表假,非0的數值代表真(負數也代表真)
  • wchar_t(Wide Character Type):寬字元型態,
    • 有些系統支援大於char的1byte的延伸字元集,要開發國際型的程式時就需使用wchar_t型態
    • 指派字面字元給wchar_t時,前面需加上L
    • wchar_t wl = L'Z'; 
      wchar_t wl = L'\x0438';
      
    • cout不適合處理wchar_t,新版的iostream提供wcinwout來處理wchar_t
  • 型態的Byte數:不同的作業系統對基本型態可能定義不同的byte數,可以用sizeof運算子來確認,用法如下:
    • sizeof(型態)
    • cout << sizeof(int) << endl;
      
    • sizeof 變數名稱
    • int num = 0; 
      cout << sizeof num << endl;
      
  • 變數型態會決定配置多大的記憶體,所以宣告的型態會影響可儲存數值的範圍。
    • 配置不夠大的範圍,多餘的部份將被捨去
    • int intValue = 9999999;
      short shortValue = 0;
      shortValue = intValue;
      cout << shortValue << endl;  //顯示 -27009
      
  • C++中各資料型態大小範圍
    資料型態
  • 前置詞(Prefix):放在數值前面,改面數值基底
    • 16進位:可用0x0X開頭的數字代表16進位數字
      • 指派16進位的A0給num1,16進位的50給num2
        int  num1 = 0xA0;
        int  num2 = 0x50;
        
    • 8進位:可用0開頭的數字代表8進位數字
      • 指派8進位的30給num1,8進位的35給num2
        int  num1 = 030;
        int  num2 = 035;
        
  • 後置詞(Postfix or Suffix):為了讓編譯器更清楚的知道數值的型態,可以在整數後面加上下列字元,
    • 後置詞不分大小寫及順序,若無標明或值沒有超過int範圍,則C++預設使用int儲存整數常數
    • 整數字尾表示法
      • L:long
        • long  num1 = 999L;
          
      • U:unsigned
        • unsigned long  num1 = 999UL;
          
    • 浮點數字尾表示法
      • F:float
        • float  num1 = 999.02F;
          
      • L:long double
        • double  num1 = 999.02L;
          
  • 進位運作子:iostream中除endl外,還定義了dechexoct等運作子,可以控制串流中數字的操作進制
    • 進位運作子可將整數以指定進制顯示
    • 進位運作子是強制式(modal)除非更改設定,否則影響會持續到程式結束
    • 進位運作子不會影響浮點數,浮點數仍會以十進位顯示
    • cout << 50;           //顯示50
      cout << hex << 50;    //將10進制的50以16進制顯示 ⇒ 顯示32
      cout << dec << 0x50;  //將16進制的0x50以10進制顯示 ⇒ 顯示80
      cout << hex << 0x50;  //將16進制的0x50以16進制顯示 ⇒ 顯示50
      
  • 科學記號表示法:數值後面接Ee再接10的乘方
    • E左邊的數字稱為假數(Mantissa),E右邊的數字稱為指數(Exponent)
    • 314.159 = 3.14159E2
      float floatValue1 = 3.14e2
      float floatValue2 = 3.14e+2
      
    科學記號表示法
  • 綜合範例
    #include "stdafx.h"
    #include <iostream>
    
    using std::cout;
    using std::endl;
    using std::dec;
    using std::hex;
    using std::oct;
    
    int main(void)
    {
      int intNum1 = 50;
      int intNum2 = 0x50;
      int intNum3 = 050;
      cout << "int = " << sizeof(int) << " bytes" << endl;
      cout << "intNum1 = " << sizeof intNum1 << " bytes" << endl;
      cout << "int 50     : " << intNum1 << endl;
      cout << "int 0x50   : " << intNum2 << endl;
      cout << "int 050    : " << intNum3 << endl << endl;    
    
      cout << "int 50     : " << dec << intNum1 << endl;
      cout << "int 0x50   : " << hex << intNum2 << endl;
      cout << "int 050    : " << oct << intNum3 << endl;
      cout << dec << endl;
    
      char charLetter1 = 'A';
      char charLetter2 = 65;
      cout << "char = " << sizeof(char) << " bytes" << endl;
      cout << "charLetter1 = " << sizeof charLetter1 << " bytes" << endl;
      cout << "char \'A\' : " << charLetter1 << endl;
      cout << "char 65    : " << charLetter2 << endl << endl;    
    
      bool boolValue1 = true;
      bool boolValue2 = false;
      bool boolValue3 = 1;
      bool boolValue4 = 0;
      cout << "bool = " << sizeof(bool) << " bytes" << endl;
      cout << "boolValue1 = " << sizeof boolValue1 << " bytes" << endl;
      cout << "bool true  : " << boolValue1 << endl;
      cout << "bool false : " << boolValue2 << endl;
      cout << "bool 1     : " << boolValue3 << endl;
      cout << "bool 0     : " << boolValue4 << endl << endl;
    
      unsigned long ulongNumber1 = 999;
      unsigned long ulongNumber2 = 999UL;
      cout << "unsigned long = " << sizeof(unsigned long) << " bytes" << endl;
      cout << "ulongNumber1 = " << sizeof ulongNumber1 << " bytes" << endl;
      cout << "unsigned long 999      : " << ulongNumber1 << endl;
      cout << "unsigned long 999UL    : " << ulongNumber2 << endl;
    
      system("PAUSE");
    }
    
    資料型態執行結果