目錄
- 整數型別
- 浮點型別(float 和 double)
- decimal 型別
- 浮點數舍入誤差
- 字面量
- 總結
在之前的文章中(地址:https://www.vinanysoft.com/c-sharp-basics/introducing/),以 HelloWorld 程式為基礎,介紹 C# 語言、它的結構、基本語法以及如何撰寫最簡單的程式有了初步理解,
接下來介紹基本的 C# 型別,繼續鞏固 C# 的基礎知識,本系列文章到目前為止只用過少量的內置資料型別,而且只是一筆帶過,在 C# 中有大量的型別,而且可以通過合并型別來創建新型別,
但 C# 有幾種型別非常簡單,是其他所有型別的基礎,它們稱為預定義型別(predefined type)或基元型別( primitive type),
C# 提供了 16 種預定義型別,如下圖所示,其中包括 13 種簡單型別和 3 種非簡單型別,

所有預定義型別的名稱都由全小寫的字母組成,預定義的簡單型別包括以下 3 種,
- 11 種數值型別,
- 不同長度的有符號和無符號整數型別,
- 用于科學計算的二進制浮點型別
float和double, - 一種用于金融計算的十進制高精度浮點型別
decimal,與float和double不同,decimal型別可以準確地表示分數,decimal型別常用于貨幣的計算,
- 一種
Unicode字符型別char, - 一種布爾型別
bool,bool型別表示布林值并且必須為true或false,
非簡單型別如下:
object,它是所有其他型別的基類,string,它是一個Unicode字符陣列,dynamic,使用動態語言撰寫的程式集時使用,
所有預定義型別都直接映射到底層的 .NET 型別,C# 的型別名稱就是 .NET 型別的別名,所以使用 .NET 的型別名稱也能很好地符合 C# 語法,不過并不鼓勵這樣做,在 C# 程式中,應該盡量使用 C# 型別名稱而不是 .NET型別名稱,
整數型別
C# 有八種整數型別,可選擇最恰當的一種來存盤資料以避免浪費資源,下表列出了 C# 支持的整型型別:
| C# 型別/關鍵字 | 范圍 | 大小 | .NET 型別 |
|---|---|---|---|
| sbyte | -128 到 127 | 8 位帶符號整數 | System.SByte |
| byte | 0 到 255 | 無符號的 8 位整數 | System.Byte |
| short | -32,768 到 32,767 | 有符號 16 位整數 | System.Int16 |
| ushort | 0 到 65,535 | 無符號 16 位整數 | System.UInt16 |
| int | -2,147,483,648 到 2,147,483,647 | 帶符號的 32 位整數 | System.Int32 |
| uint | 0 到 4,294,967,295 | 無符號的 32 位整數 | System.UInt32 |
| long | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 64 位帶符號整數 | System.Int64 |
| ulong | 0 到 18,446,744,073,709,551,615 | 無符號 64 位整數 | System.UInt64 |
C# 所有基元型別都有短名稱(最左列)和完整名稱(最右列),完整名稱對應 BCL(基類別庫)中的型別名稱,
由于基元資料型別是其他型別的基礎,所以 C# 為基元資料型別的完整名稱提供了短名稱(或稱為縮寫),其實從編譯器的角度看,兩種名稱完全一樣,最終都生成相同的代碼,事實上,檢查最終生成的 CIL 代碼,根本看不出源代碼具體使用的名稱,
例如,以下宣告宣告了相同型別的變數:
int a = 123;
System.Int32 b = 123;
C# 支持完整 BCL 名稱和關鍵字,造成開發人員犯難在什么時候用什么,不要時而用這個,時而用那個,最好堅持用一種,
C# 開發人員一般用 C# 關鍵字,例如,用 int 而不是 System.Int32,用 string 而不是 System.String(甚至不要用 String 這種簡化形式),
浮點型別(float 和 double)
C# 支持以下預定義浮點型別:
| C# 型別/關鍵字 | 大致范圍 | 精度 | 大小 | .NET 型別 |
|---|---|---|---|---|
| float | ±1.5 x 10?45 至 ±3.4 x 1038 | 大約 6-9 位數字 | 4 個位元組 | System.Single |
| double | ±5.0 × 10?324 到 ±1.7 × 10308 | 大約 15-17 位數字 | 8 個位元組 | System.Double |
在上表中,最左側列中的每個 C# 型別關鍵字都是相應 .NET 型別的別名, 它們是可互換的, 例如,以下宣告宣告了相同型別的變數:
double a = 12.3;
System.Double b = 12.3;
decimal 型別
| C# 型別/關鍵字 | 大致范圍 | 精度 | 大小 | .NET 型別 |
|---|---|---|---|---|
| decimal | ±1.0 x 10-28 至 ±7.9228 x 1028 | 28-29 位 | 16 個位元組 | System.Decimal |
與 float 和 double 相比,decimal 型別具有更高的精度和更小的范圍,因此它適合于財務和貨幣計算,
浮點數舍入誤差
float 和 double 在內部都是基于 2 來表示數值的,因此只有基于 2 表示的數值才能夠精確表示,事實上,這意味著大多數有小數部分的字面量(它們都基于 10)將無法精確表示,例如:
float f1 = 1F;
float f2 = 0.9F;
Console.WriteLine(f1 - f2);
double d1 = 1D;
double d2 = 0.9D;
Console.WriteLine(d1 - d2);
decimal decimal1 = 1M;
decimal decimal2 = 0.9M;
Console.WriteLine(decimal1 - decimal2);
輸出
0.100000024
0.09999999999999998
0.1
這就是為什么 float 和 double 不適合金融計算,相反,decimal 基于 10,它能夠精確表示基于 10 的數值(也包括它的因數,基于 2 和基于 5 的數值),因為實數的字面量都是基于 10 的,所以 decimal 能夠精確表示像 0.1 這樣的數,然而,float、double 和 decimal 都不能精確表示那些基于 10 的回圈小數:
decimal m = 1M / 6M;
Console.WriteLine(m);
decimal m2 = m + m + m + m + m + m;
Console.WriteLine(m2);
Console.WriteLine();
double d = 1d / 6d;
Console.WriteLine(d);
double d2 = d + d + d + d + d + d;
Console.WriteLine(d2);
輸出
0.1666666666666666666666666667
1.0000000000000000000000000002
0.16666666666666666
0.9999999999999999
字面量
字面量(literal value)表示源代碼中的固定值,
Console.WriteLine(123);
Console.WriteLine(456.789);
默認情況下,輸入帶小數點的字面量,編譯器自動把它解釋成 double 型別, 如果輸入的是整數值(沒有小數點)通常默認為 int, 如果值太大,以至于無法用 int 來存盤,編譯器會把它解釋成 long,
static void Main(string[] args)
{
var expectIsInt = 123;
var expectIsLong = 9223372036854775807;
var expectIsDouble = 3.14;
Console.WriteLine($"expectIsInt 的型別是:{expectIsInt.GetType().Name};" +
$"expectIsLong 的型別是:{expectIsLong.GetType().Name};" +
$"expectIsDouble 的型別是:{expectIsDouble.GetType().Name}");
}
輸出
expectIsInt 的型別是:Int32;expectIsLong 的型別是:Int64;expectIsDouble 的型別是:Double
由于帶小數點的值默認為 double 型別,所以下面輸出的結果中,超過可容納的精度部分會被丟棄,
static void Main(string[] args)
{
Console.WriteLine(5.141231231234567898765);
}
輸出
5.141231231234568
要顯示具有完整精度的數字,必須將字面量顯式宣告為 decimal 型別,通過追加一個 M(或者 m)來實作,
static void Main(string[] args)
{
Console.WriteLine(5.141231231234567898765M);
}
輸出
5.141231231234567898765
還可以使用 F 和 D 作為后綴,將字面量分別顯式宣告為 float 或者 double, 對于整數資料型別,整數字面量的型別是像下面這樣確定的:
-
如果整數字面量沒有后綴,則其型別為以下型別中可表示其值的第一個型別:
int、uint、long、ulong, -
如果整數字面量以
U或u為后綴,則其型別為以下型別中可表示其值的第一個型別:uint、ulong, -
如果整數字面量以
L或l為后綴,則其型別為以下型別中可表示其值的第一個型別:long、ulong,備注:可以使用小寫字母
l作為后綴, 但是,這會生成一個編譯器警告,因為字母l可能與數字1混淆, 為清楚起見,請使用L, -
如果整數字面量的后綴為
UL、Ul、uL、ul、LU、Lu、lU或lu,則其型別為ulong,
字面量的后綴不區分大小寫,但一般推薦大寫,避免出現小寫字母 l 和數字 1 不好區分的情況,
從 C# 7.0 開始提供支持將 _ 用作數字分隔符,可以將數字分隔符用于所有型別的數字文本,
double d = 3D;
d = 4d;
d = 3.934_001;
float f = 3_000.5F;
f = 5.4f;
decimal myMoney = 3_000.5m;
myMoney = 400.75M;
C# 支持使用科學記數法,指數記數法要求使用 e 或 E 中綴,在中綴字母后面添加正整數或者負整數,并在字面量最后添加恰當的資料型別后綴,
double d = 0.42e2;
Console.WriteLine(d); // output 42;
float f = 134.45E-2f;
Console.WriteLine(f); // output: 1.3445
decimal m = 1.5E6m;
Console.WriteLine(m); // output: 1500000
使用 0x 或 0X 前綴表示十六進制計數法,在 C# 7.0 和更高版本中使用 0b 或 0B 前綴表示二進制計數法,
var hexLiteral = 0x2A;
var binaryLiteral = 0b_0010_1010;
總結
C# 語言的基元型別包括八種整數型別、兩種用于科學計算的二進制浮點型別、一種用于金融計算的十進制浮點型別,浮點型存在舍入誤差,使用的時候要注意,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/91566.html
標籤:C#
