2.2.1 C#8.0教程 精講基本數據類型 - 數值型

.NET 在它的類庫中定義了數千種類型,你也可以自己定義編寫,所以 C# 可以處理無限數量的數據類型。但是,編譯器對少數類型進行特殊處理,預製了大量的方法,簡化我們的使用。例如下面代碼:

// 示例 1

string strUserName = "Frank" + " " + "Gao";

示例1.很方便的進行了字符串連接操作。但它之所以有效,是因為c#編譯器知道字符串類型,併為它們提供了特殊的服務( C#規範中有一部分為 +操作符 定義了唯一的字符串處理)。C# 不僅為字符串提供了各種特殊服務,還為某些數值數據類型、布爾值、稱為元組的類型家族以及稱為動態和對象的兩種特定類型提供了特殊服務。它們中的大多數不僅對 C# 很特殊,而且對運行時也很特殊——幾乎所有的數字類型(除了BigInteger外)都在中間語言(IL)中得到了直接支持,而 bool 、string 和 object 類型在 Runtime 階段執行效率也非常高。

  1. 整數類型
  2. 浮點類型
  3. 特殊的decimal類型
  4. 默認數字類型
  5. 類型後綴
  6. 分組計數表示
  7. 科學計數法
  8. 十六進制、二進制

整數類型

C#支持整數和浮點運算。有帶符號的和無符號的整數類型,它們有不同的大小,如圖1.所示。最常用的整數類型是int,主要是因為它足夠大,可以表示範圍廣泛的正負整數值,同時也不會因為太大而無法在所有支持 .NET 的 CPU 上有效工作。是效率最高的整數類型之一。

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

圖1. 基本數據類型

圖1.中的第二列顯示了CLR中的類型名稱。不同的語言有不同的命名約定,C# 使用來自其 C語言 詞根的名稱來命名數值類型(圖1.第一列),但是這些不符合 .NET 對其數據類型的命名約定。就運行時而言,第二列中的名稱是真正的名稱——有各種各樣的 API 可以在運行時報告關於類型的信息,它們報告是這些 CLR 的名稱(圖1.第二列),而不是C#的類型名稱(圖1.第一列)。兩列名稱在 C# 源代碼中是同義詞或稱為別名,所以如果你想使用運行時名稱,你可以自由使用,但是 C# 類型名稱在風格上更類似 C語言。由於編譯器處理這些類型的方式不同於其他類型,因此在這裡特別強調一下這種情況。

浮點類型

C# 還支持浮點數。有兩種類型:float和double,它們是標準IEEE 754格式的32位和64位數字,如圖2.中的CLR名稱所示,它們對應於通常稱為單精度和雙精度的數字。浮點值的工作方式與整數不同,因此此表與整數類型表略有不同。浮點數存儲一個值和一個指數(在概念上類似於科學表示法,但使用的是二進制而不是十進制)。精度列(第四列)顯示值部分有多少位可用,範圍(第五列)表示為最小的非零值和最大值。(可以是正的,也可以是負的。)

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

圖2. 單精度、雙精度浮點類型

特殊的decimal類型

C# 識別第三種數字表示形式,稱為 decimal(在CLR中稱為 System.Decimal)。這是一個128位的值,因此它可以提供比其他類型更高的精度,但它不僅僅是 double 的更大版本。它是為需要可預測處理小數部分的計算而設計的,這是 float 和 double 都不能提供的。如果您編寫的代碼將一個 float 類型的變量初始化為0,然後在一行中向它添加了9次0.1(如圖3.所示),那麼您可能期望得到0.9,但實際上您將得到大約0.9000001。這是因為IEEE 754用二進制存儲數字,二進制不能表示所有的小數部分。

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

圖3. 意外的結果

十進制整數轉換成二進制的方法 “除2倒取餘”。所以每一個十進制整數都能對應出準確的二進制數。

十進制小數轉換成二進制的方法 “乘2正取整”。所以十進制小數不一定能夠對應出準確的二進制數,有可能會一直乘下去。就像沒法用十進制精確表示 1/3 一樣。

至於為什麼要牽扯進去二進制,以及轉換方法,如果搞不明白,請跳過過程,記住結論即可。

這意味著 float 和 double 對於部分小數來說只能表示其近似值。但這並不總是很明顯的,因為精度損失太小,在將浮點數轉換為文本時,它們被四捨五入為十進制近似,這可以掩蓋差異。但經過多次計算,誤差往往會累積起來,最終產生令人驚訝的結果。

對於某些數學運算,這並不重要。例如在模擬或信號轉換處理中,一些噪聲和誤差是正常可接受的。但會計師和金融監管機構往往不那麼寬容——像這樣的小差異可能會讓它看起來像是金錢神奇地消失了或出現了。我們需要對涉及金錢的計算做到絕對準確,這使得浮點數對於這樣的工作來說是一個糟糕的選擇。這就是為什麼 C# 提供了

decimal 類型,它提供了良好定義的十進制精度級別。

decimal 需要根據實際情況使用。主要原因是大多數整數類型可以由CPU本地處理(在64位進程中運行時,它們都可以得到完美支持)。同樣,許多cpu可以直接使用float和double類型。但是,它們都沒有對 decimal 的內在支持,這意味著即使是簡單的操作,比如加法,也需要多個CPU指令。這意味著使用 decimal 進行的算術運算要比使用到目前為止所顯示的其他數字類型慢得多。大家可以參考圖4.查看兩種類型變量計算相差時間,還是很明顯的。

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

圖4.橙色箭頭代表 float 時間,紅色箭頭代表 decimal 時間

默認數字類型

在使用數字值時,C# 編譯器會自動推斷該值的類型。如數字 123 會自動推斷為 int 類型,3000000000 推為 uint , 5000000000 推為 long 1.23 推為 double 型。這是編譯器裡寫死的,請不要對著幹,例如下方語句:

float f=0.1; // 編譯錯誤

編譯時會提示:Literal of type double cannot be implicitly converted to type 'float'; use an 'F' suffix to create a literal of this type

類型後綴

如果你要打破此規定,可以通過添加後綴告訴編譯器您需要特定的類型。123U是uint, 123L是long,123UL是ulong

。後綴字母是獨立於大小寫和順序的,所以可以用123Lu、123UL或其他任何排列代替123UL,都表示無符號長整型。對於 double float decimal,分別使用D、F和M後綴。

分組計數表示

如果你處理的是非常大的數,很容易把0的數量弄錯。這可能非常昂貴或危險,這取決於你的應用程序所使用的領域。C# 提供了一些解決方法,允許您在數字文本的任何地方添加 下劃線,以便分解數字。這類似於大多數英語國家使用逗號將每3位編成一組的常見做法。例如,大多數以英語為母語的人不會寫5000000000,而是會寫500,000,000,000,這樣就能立即看出這是50億,而不是500億或5億。(世界上有幾個國家用句號表示,他們會寫成5.000.000.000)。在C#中,我們可以通過將數字寫為5_000_000_000來便於計位,在編譯器看來,會忽略 下劃線_ ,等同於5000000000。

科學計數法

當然,你還可直接使用科學計數法來使用數字。如下圖5.所示 0.618×10¹ = 0.618E1 。

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

圖5. 科學計數法

十六進制、二進制

能夠用十六進制編寫整數值通常很有用,因為這些數字能更好地映射到運行時使用的二進制數值。當一個數字的不同位表示不同的東西時,這一點特別重要。例如,您可能需要處理源自Windows系統調用的數字錯誤代碼——Windows偶爾出現異常很正常。這些代碼一般使用第一位的位表示成功或失敗,接下來的幾個位表示錯誤的起源,剩下的位標識特定的錯誤。例如,COM錯誤代碼E_ACCESSDENIED的值為−2,147,024,891。很難看到十進制的結構,但在十六進制中,它更容易:80070005。8表示這是一個錯誤(十六進制8 = 二進制1000),接下來的007表示這最初是一個普通的Win32錯誤,已經被翻譯成一個COM錯誤。剩下的位表示Win32錯誤代碼為5 (ERROR_ACCESS_DENIED)。C#允許您在類似的場景中使用十六進制編寫整數值,其中十六進制表示更具可讀性。您只需在數字前面加上0x,因此在本例中,您將寫入0x80070005。

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

圖6. 經典的藍屏,注意錯誤代碼0x開頭

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

變量i 被賦值為十六進制數

您還可以使用0b前綴編寫二進制文字。數字分隔符可以在十六進制和二進制中使用,就像它們可以在小數中使用一樣,儘管在這些情況下更常見的是將數字按4分組,例如0b_0010_1010。顯然,這使得數字中的任何二進制結構都比十六進制更明顯,但是32位二進制長得不方便,這就是為什麼我們經常使用十六進制來代替。

2.2.1 C#8.0教程 精講基本數據類型 - 數值型

變量i 被賦值為二進制數

如果您不瞭解二進制、十六進制,不知道為何最後的輸出結果為6.28,那麼你還是先從更基礎的知識開始學起吧。

本課小結

這節課作者也收穫頗多,有很多都是根據 Microsoft 的官方文檔查閱而來。尤其是關於精度的問題。又有了更深的理解。


分享到:


相關文章: