Compartilhar via


Solucionando problemas de tipos de dados (Visual Basic)

This page lists some common problems that can occur when you perform operations on intrinsic data types.

Floating-Point Expressions Do Not Compare as Equal

When you work with floating-point numbers (Tipo de dados único (Visual Basic) and Tipo de dados duplo (Visual Basic)), remember that they are stored as binary fractions. Isso significa que eles não podem conter uma representação exata de qualquer quantidade que não seja uma fração binário (do formulário k / (2 ^ n) onde k e n são números inteiros). For example, 0.5 (= 1/2) and 0.3125 (= 5/16) can be held as precise values, whereas 0.2 (= 1/5) and 0.3 (= 3/10) can be only approximations.

Because of this imprecision, you cannot rely on exact results when you operate on floating-point values. In particular, two values that are theoretically equal might have slightly different representations.

To compare floating-point quantities

  1. Calculate the absolute value of their difference by using the Abs method of the Math class in the System namespace.

  2. Determine an acceptable maximum difference, such that you can consider the two quantities to be equal for practical purposes if their difference is no larger.

  3. Compare the absolute value of the difference to the acceptable difference.

The following example demonstrates both incorrect and correct comparison of two Double values.

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))

The previous example uses the ToString method of the Double structure so that it can specify better precision than the CStr keyword uses. The default is 15 digits, but the "G17" format extends it to 17 digits.

Mod Operator Does Not Return Accurate Result

Because of the imprecision of floating-point storage, the Operador Mod (Visual Basic) can return an unexpected result when at least one of the operands is floating-point.

The Tipo de dados decimais (Visual Basic) does not use floating-point representation. Many numbers that are inexact in Single and Double are exact in Decimal (for example 0.2 and 0.3). Although arithmetic is slower in Decimal than in floating-point, it might be worth the performance decrease to achieve better precision.

To find the integer remainder of floating-point quantities

  1. Declare variables as Decimal.

  2. Use the literal type character D to force literals to Decimal, in case their values are too large for the Long data type.

The following example demonstrates the potential imprecision of floating-point operands.

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))

O exemplo anterior usa o ToStringométodo da Doubleestrutura , de modo que ele pode especificar a precisão do melhor que o CStrusa apalavra-chave . The default is 15 digits, but the "G17" format extends it to 17 digits.

Because zeroPointTwo is Double, its value for 0.2 is an infinitely repeating binary fraction with a stored value of 0.20000000000000001. Dividing 2.0 by this quantity yields 9.9999999999999995 with a remainder of 0.19999999999999991.

In the expression for decimalRemainder, the literal type character D forces both operands to Decimal, and 0.2 has a precise representation. Therefore the Mod operator yields the expected remainder of 0.0.

Note that it is not sufficient to declare decimalRemainder as Decimal. You must also force the literals to Decimal, or they use Double by default and decimalRemainder receives the same inaccurate value as doubleRemainder.

Boolean Type Does Not Convert to Numeric Type Accurately

Tipo de dados booleanos (Visual Basic) values are not stored as numbers, and the stored values are not intended to be equivalent to numbers. For compatibility with earlier versions, Visual Basic provides conversion keywords (Função CType (Visual Basic), CBool, CInt, and so on) to convert between Boolean and numeric types. However, other languages sometimes perform these conversions differently, as do the .NET Framework methods.

You should never write code that relies on equivalent numeric values for True and False. Whenever possible, you should restrict usage of Boolean variables to the logical values for which they are designed. If you must mix Boolean and numeric values, make sure that you understand the conversion method that you select.

Conversion in Visual Basic

Quando você usa o CType ou CBool as palavras-chave de conversão para converter tipos de dados numéricos para Boolean, 0 se torna False e todos os outros valores que se tornam True. When you convert Boolean values to numeric types by using the conversion keywords, False becomes 0 and True becomes -1.

Conversion in the Framework

The ToInt32 method of the Convert class in the System namespace converts True to +1.

If you must convert a Boolean value to a numeric data type, be careful about which conversion method you use.

Character Literal Generates Compiler Error

In the absence of any type characters, Visual Basic assumes default data types for literals. The default type for a character literal — enclosed in quotation marks (" ") — is String.

The String data type does not widen to the Caractere tipo de dados (Visual Basic). This means that if you want to assign a literal to a Char variable, you must either make a narrowing conversion or force the literal to the Char type.

To create a Char literal to assign to a variable or constant

  1. Declare the variable or constant as Char.

  2. Enclose the character value in quotation marks (" ").

  3. Follow the closing double quotation mark with the literal type character C to force the literal to Char. This is necessary if the type checking switch (Opção declaração estrito) is On, and it is desirable in any case.

The following example demonstrates both unsuccessful and successful assignments of a literal to a Char variable.

Option Strict On
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")

There is always a risk in using narrowing conversions, because they can fail at run time. For example, a conversion from String to Char can fail if the String value contains more than one character. Therefore, it is better programming to use the C type character.

String Conversion Fails at Run Time

O Tipo de dados de sequência de caracteres (Visual Basic) participa muito poucas conversões de expansão. Stringamplia-se somente a mesmo e Objecte apenas Char e Char() (um Char array) aumentarão para String. This is because String variables and constants can contain values that other data types cannot contain.

When the type checking switch (Opção declaração estrito) is On, the compiler disallows all implicit narrowing conversions. This includes those involving String. Your code can still use conversion keywords such as CStr and Função CType (Visual Basic), which direct the .NET Framework to attempt the conversion.

ObservaçãoObservação

O erro de conversão-restrição é suprimida para conversões de elementos em um For Each…Next variávelde controle decoleção para o loop . Para obter mais informações e exemplos, consulte "Restringir conversões" seção Instrução For Each...Next (Visual Basic).

Narrowing Conversion Protection

The disadvantage of narrowing conversions is that they can fail at run time. For example, if a String variable contains anything other than "True" or "False," it cannot be converted to Boolean. If it contains punctuation characters, conversion to any numeric type fails. Unless you know that your String variable always holds values that the destination type can accept, you should not try a conversion.

If you must convert from String to another data type, the safest procedure is to enclose the attempted conversion in the Instrução Try...Catch...Finally (Visual Basic). This lets you deal with a run-time failure.

Character Arrays

A single Char and an array of Char elements both widen to String. However, String does not widen to Char(). To convert a String value to a Char array, you can use the ToCharArray method of the System.String class.

Meaningless Values

In general, String values are not meaningful in other data types, and conversion is highly artificial and dangerous. Whenever possible, you should restrict usage of String variables to the character sequences for which they are designed. You should never write code that relies on equivalent values in other types.

Consulte também

Referência

Resumo de tipo de dados (Visual Basic)

Funções de conversão de tipo (Visual Basic)

Conceitos

Tipos de dados no Visual Basic

Caracteres de tipo (Visual Basic)

Programação Sem-Tipos no Visual Basic

Uso eficiente de tipos de dados (Visual Basic)

Outros recursos

Implementação de tipos de dados (Visual Basic)

Conversões de Tipo no Visual Basic