疑難排解資料類型 (Visual Basic)
此頁面列出當您對內建資料類型執行作業時可能發生的一些常見問題。
浮點運算式並未比較為相等
當您使用浮點數 (單一資料類型和雙精確度資料類型) 時,請記住其會儲存為二進位分數。 這表示其不能保留確切表示任何不是 k / (2 ^) n 格式的二進位分數 (其中 k 和 n 是整數)。 例如,0.5 (= 1/2) 和 0.3125 (= 5/16) 可以保留為精確值,而 0.2 (= 1/5) 和 0.3 (= 3/10) 只能是近似值。
由於這種不精確,因此當您在浮點值上操作時,無法依賴確切的結果。 特別是,理論上相等的兩個值可能會有稍微不同的表示。
若要比較浮點數量 |
---|
1. 使用 System 命名空間中 Math 類別的 Abs 方法,計算其差異的絕對值。 2. 判斷可接受的最大差異,如此一來,如果兩個數量的差異不較大,您可以將兩個數量視為相等。 3. 比較差異的絕對值與可接受的差異。 |
下列範例示範兩個 Double
值的不正確和正確比較。
Dim oneThird As Double = 1.0 / 3.0
Dim pointThrees As Double = 0.333333333333333
' The following comparison does not indicate equality.
Dim exactlyEqual As Boolean = (oneThird = pointThrees)
' The following comparison indicates equality.
Dim closeEnough As Double = 0.000000000000001
Dim absoluteDifference As Double = Math.Abs(oneThird - pointThrees)
Dim practicallyEqual As Boolean = (absoluteDifference < closeEnough)
MsgBox("1.0 / 3.0 is represented as " & oneThird.ToString("G17") &
vbCrLf & "0.333333333333333 is represented as " &
pointThrees.ToString("G17") &
vbCrLf & "Exact comparison generates " & CStr(exactlyEqual) &
vbCrLf & "Acceptable difference comparison generates " &
CStr(practicallyEqual))
上一個範例會使用 Double 結構的 ToString 方法,以便可以指定比 CStr
關鍵字使用的更佳精確度。 預設值為 15 位數,但「G17」格式會將其延伸至 17 位數。
Mod 運算子並未傳回精確的結果
由於浮點儲存的不精確,因此當至少有一個運算元是浮點時,Mod 運算子可能會傳回非預期的結果。
十進位資料類型不會使用浮點表示。 許多在 Single
和 Double
中不精確的數字在 Decimal
中為精確 (例如 0.2 和 0.3)。 雖然算術在 Decimal
中的速度比浮點慢,但效能可能會降低,以達到更好的精確度。
尋找浮點數量的整數餘數 |
---|
1. 將變數宣告為 Decimal 。2. 使用常值型別字元 D 將常值強制為 Decimal ,以防其值對 Long 資料類型而言太大。 |
下列範例示範浮點運算元可能出現的不精確。
Dim two As Double = 2.0
Dim zeroPointTwo As Double = 0.2
Dim quotient As Double = two / zeroPointTwo
Dim doubleRemainder As Double = two Mod zeroPointTwo
MsgBox("2.0 is represented as " & two.ToString("G17") &
vbCrLf & "0.2 is represented as " & zeroPointTwo.ToString("G17") &
vbCrLf & "2.0 / 0.2 generates " & quotient.ToString("G17") &
vbCrLf & "2.0 Mod 0.2 generates " &
doubleRemainder.ToString("G17"))
Dim decimalRemainder As Decimal = 2D Mod 0.2D
MsgBox("2.0D Mod 0.2D generates " & CStr(decimalRemainder))
上一個範例會使用 Double 結構的 ToString 方法,以便可以指定比 CStr
關鍵字使用的更佳精確度。 預設值為 15 位數,但「G17」格式會將其延伸至 17 位數。
因為 zeroPointTwo
是 Double
,其 0.2 的值是無限重複的二進位分數,其儲存值為 0.20000000000000001。 將 2.0 除以此數量會產生 9.9999999999999995,餘數為 0.19999999999999991。
在 decimalRemainder
的運算式中,常值型別字元 D
會將兩個運算元都強制為 Decimal
,而 0.2 具有精確的表示。 因此,Mod
運算子會產生預期的餘數 0.0。
請注意,其不足以宣告 decimalRemainder
為 Decimal
。 您也必須強制常值為 Decimal
,否則其預設會使用 Double
,而 decimalRemainder
會接收與 doubleRemainder
相同的不精確值。
布林值型別並未精確轉換成數值型別
布林值資料類型值不會儲存為數字,且儲存的值不等於數字。 為了與舊版相容,Visual Basic 提供轉換關鍵字 (CType 函式、CBool
、CInt
等),以在 Boolean
和數值型別之間轉換。 不過,其他語言有時會以不同的方式執行這些轉換,就像.NET Framework方法一樣。
您絕不應該撰寫依賴 True
和 False
對等數值的程式碼。 您應該盡可能將 Boolean
變數的使用限制在當初所設計的邏輯值上。 如果您必須混合 Boolean
和數值,請確定您了解所選取的轉換方法。
Visual Basic 中的轉換
當您使用 CType
或 CBool
轉換關鍵字將數值資料類型轉換成 Boolean
時,0 會變成 False
,而所有其他值都會變成 True
。 當您使用轉換關鍵字將 Boolean
值轉換成數值型別時,False
會變成 0,而 True
會變成 -1。
Framework 中的轉換
System 命名空間中 Convert 類別的 ToInt32 方法會將 True
轉換成 +1。
如果您必須將 Boolean
值轉換成數值資料類型,請留意您使用的轉換方法。
字元常值產生編譯器錯誤
如果沒有任何類型字元,Visual Basic 會假設常值的預設資料類型。 字元常值的預設類型以引號 (" "
) 括住,也就是 String
。
String
資料類型不會擴大為 Char 資料型別。 這表示如果您想要將常值指派給 Char
變數,則必須進行縮小轉換,或強制常值轉換為 Char
類型。
建立 Char 常值以指派給變數或常數 |
---|
1. 將變數或常數宣告為 Char 。2. 以引號 ( " " ) 括住字元值。3. 在右邊雙引號結尾加上常值型別字元 C ,將常值強制為 Char 。 如果類型檢查參數 (Option Strict 陳述式) 是 On 則為必要,且在任何情況下都是必要的。 |
下列範例示範將常值指派給 Char
變數的失敗和成功。
Dim charVar As Char
' The following statement attempts to convert a String literal to Char.
' Because Option Strict is On, it generates a compiler error.
charVar = "Z"
' The following statement succeeds because it specifies a Char literal.
charVar = "Z"c
' The following statement succeeds because it converts String to Char.
charVar = CChar("Z")
使用縮小轉換時一律會有風險,因為其在執行階段可能會失敗。 例如,如果 String
值包含一個以上的字元,則從 String
轉換為 Char
會失敗。 因此,使用 C
類型字元是較佳的程式設計。
字串轉換在執行階段失敗
字串資料類型參與非常少的放大轉換。 String
只會放大至其本身和 Object
,且只有 Char
和 Char()
(Char
陣列) 會放大為 String
。 這是因為 String
變數和常數可以包含其他資料類型不能包含的值。
當類型檢查參數 (Option Strict 陳述式) 為 On
時,編譯器不允許所有隱含的縮小轉換。 這包括涉及 String
的轉換。 您的程式碼仍然可以使用 轉換關鍵字,例如 CStr
和CType 函式,以指示.NET Framework嘗試轉換。
注意
從 For Each…Next
集合中的項目轉換成迴圈控制項變數時,系統會隱藏縮小轉換錯誤。 如需詳細資訊和範例,請參閱 For Each...Next 陳述式中的「縮小轉換」一節。
縮小轉換保護
縮小轉換的缺點是可能會在執行階段失敗。 例如,如果 String
變數包含「True」或「False」以外的任何項目,則無法轉換成 Boolean
。 如果包含標點符號字元,則轉換為任何數值型別都會失敗。 除非您知道 String
變數一律會保存目的地類型可接受的值,否則您不應該嘗試轉換。
如果您必須從 String
轉換成另一個資料類型,最安全的程序是將嘗試的轉換以 Try...Catch...Finally 陳述式括住。 這可讓您處理執行階段失敗。
字元陣列
單一 Char
和 Char
項目的陣列會放大為 String
。 不過,String
不會放大為 Char()
。 若要將 String
值轉換成 Char
陣列,您可以使用 System.String 類別的 ToCharArray 方法。
無意義值
一般而言,String
值在其他資料類型中沒有意義,且轉換非常不自然且危險。 您應該盡可能將 String
變數的使用限制在當初所設計的字元序列上。 您絕不應該撰寫依賴其他類型中對等值的程式碼。