このページでは、組み込みデータ型に対して操作を実行するときに発生する可能性がある一般的な問題の一覧を示します。
Floating-Point 式が等しいと比較されない
浮動小数点数 (単一データ型 と 倍精度浮動小数点型) を使用する場合は、二項分数として格納されていることに注意してください。 つまり、k と n が整数である場合、2 項分数 (形式 k/ (2 ^ n) ではない数量の正確な表現を保持することはできません。 たとえば、0.5 (= 1/2) と 0.3125 (= 5/16) は正確な値として保持できますが、0.2 (= 1/5) と 0.3 (= 3/10) は近似値にのみできます。
この不正確さのため、浮動小数点値を操作するときに正確な結果に依存することはできません。 特に、理論的に等しい 2 つの値には、少し異なる表現が含まれる場合があります。
| 浮動小数点の数量を比較するには |
|---|
| 1. System名前空間のMath クラスのAbsメソッドを使用して、差の絶対値を計算します。 2. 許容できる最大差異を決定します。この差が大きくなっていない場合は、2 つの数量を実際の目的で等しいと見なすことができます。 3. 差の絶対値を許容差と比較します。 |
次の例は、2 つの 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 演算子が正確な結果を返さない
浮動小数点ストレージが不正確であるため、少なくとも 1 つのオペランドが浮動小数点の場合、 Mod 演算子 は予期しない結果を返すことができます。
Decimal データ型では、浮動小数点表現は使用されません。
SingleとDoubleで不正確な多くの数値は、Decimalで正確です (例: 0.2 と 0.3)。
Decimalの算術演算は浮動小数点よりも遅くなりますが、精度を高めるためにパフォーマンスを低下させる価値がある場合があります。
| 浮動小数点数量の整数剰余を検索するには |
|---|
1. 変数を Decimalとして宣言します。2. リテラル型の文字 Dを使用して、Longデータ型の値が大きすぎる場合にリテラルを強制的にDecimalします。 |
次の例は、浮動小数点オペランドの潜在的な不正確さを示しています。
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.200000000000001 の無限に繰り返される二項分数です。 2.0 をこの数量で除算すると、9.999999999999999995、残りの部分は 0.19999999999999999991 になります。
decimalRemainderの式では、リテラル型の文字Dは両方のオペランドを強制的にDecimalし、0.2 は正確な表現を持ちます。 したがって、 Mod 演算子は、期待される残りの 0.0 を生成します。
decimalRemainderをDecimalとして宣言するだけでは不十分であることに注意してください。 また、リテラルを強制的にDecimalするか、既定でDoubleを使用し、decimalRemainderdoubleRemainderと同じ不正確な値を受け取る必要があります。
ブール型が数値型に正確に変換されない
ブール型の 値は数値として格納されず、格納された値は数値と等しいものではありません。 以前のバージョンとの互換性のために、Visual Basic には、Boolean型と数値型の間で変換するための変換キーワード (CType 演算子、CBool、CIntなど) が用意されています。 ただし、他の言語では、.NET Framework メソッドと同様に、これらの変換の実行方法が異なる場合があります。
TrueとFalseに等価の数値に依存するコードは記述しないでください。 可能な限り、 Boolean 変数の使用を、それらが設計されている論理値に制限する必要があります。
Booleanと数値を混在させる必要がある場合は、選択した変換方法を理解していることを確認してください。
Visual Basic での変換
CTypeまたはCBool変換キーワードを使用して数値データ型をBooleanに変換すると、0 がFalseになり、その他のすべての値がTrueになります。 変換キーワードを使用して Boolean 値を数値型に変換すると、 False は 0 になり、 True は -1 になります。
フレームワークでの変換
System名前空間のConvert クラスのToInt32 メソッドは、Trueを +1 に変換します。
Boolean値を数値データ型に変換する必要がある場合は、使用する変換方法に注意してください。
文字リテラルがコンパイラ エラーを生成する
型文字がない場合、Visual Basic ではリテラルの既定のデータ型が想定されます。 引用符 (" ") で囲まれた文字リテラルの既定の型は String。
Stringデータ型は Char データ型に拡大されません。 つまり、リテラルを Char 変数に割り当てる場合は、縮小変換を行うか、リテラルを Char 型に強制する必要があります。
| 変数または定数に割り当てる Char リテラルを作成するには |
|---|
1. 変数または定数を Charとして宣言します。2. 文字値を引用符 ( " ") で囲みます。3. リテラルを強制的に Charするには、リテラル型の文字Cで終わりの二重引用符に従います。 これは、型チェック スイッチ (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..」の「縮小変換」セクションを参照してください。次のステートメント。
縮小変換保護
縮小変換の欠点は、実行時に失敗する可能性があることです。 たとえば、 String 変数に "True" または "False" 以外の変数が含まれている場合、 Booleanに変換することはできません。 句読点文字が含まれている場合、任意の数値型への変換は失敗します。
String変数が、変換先の型で受け入れ可能な値を常に保持していることがわかっている場合を除き、変換を試すべきではありません。
Stringから別のデータ型に変換する必要がある場合は、試行された変換を Try で囲むのが最も安全な手順です。捕まえる。。。Finally ステートメント。 これにより、実行時エラーに対処できます。
文字配列
1 つの Char と Char 要素の配列の両方が Stringに拡大されます。 ただし、 String は Char()に拡大されません。
String値をChar配列に変換するには、System.String クラスの ToCharArray メソッドを使用できます。
意味のない値
一般に、 String 値は他のデータ型では意味を持たないため、変換は非常に人為的で危険です。 可能な限り、 String 変数の使用を、それらが設計されている文字シーケンスに制限する必要があります。 他の型の同等の値に依存するコードを記述しないでください。
こちらも参照ください
.NET