Solucionando problemas de tipos de dados (Visual Basic)Troubleshooting Data Types (Visual Basic)

Esta página lista alguns problemas comuns que podem ocorrer quando você executa operações em tipos de dados intrínsecos.This page lists some common problems that can occur when you perform operations on intrinsic data types.

As expressões de ponto flutuante não são comparadas como iguaisFloating-Point Expressions Do Not Compare as Equal

Quando você trabalha com números de ponto flutuante (tipo de dados único e tipo de dados duplo), lembre-se de que eles são armazenados como frações binárias.When you work with floating-point numbers (Single Data Type and Double Data Type), remember that they are stored as binary fractions. Isso significa que eles não podem manter uma representação exata de qualquer quantidade que não seja uma fração binária (do formulário k/(2 ^ n) em que k e n são inteiros).This means they cannot hold an exact representation of any quantity that is not a binary fraction (of the form k / (2 ^ n) where k and n are integers). Por exemplo, 0,5 (= 1/2) e 0,3125 (= 5/16) podem ser mantidos como valores precisos, enquanto 0,2 (= 1/5) e 0,3 (= 3/10) podem ser apenas aproximações.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.

Devido a essa imprecisão, você não pode contar com resultados exatos ao operar em valores de ponto flutuante.Because of this imprecision, you cannot rely on exact results when you operate on floating-point values. Em particular, dois valores que são teoricamente iguais podem ter representações ligeiramente diferentes.In particular, two values that are theoretically equal might have slightly different representations.

Para comparar as quantidades de ponto flutuanteTo compare floating-point quantities
1. calcule o valor absoluto de sua diferença usando o método Abs da classe Math no namespace System.1. Calculate the absolute value of their difference by using the Abs method of the Math class in the System namespace.
2. Determine uma diferença máxima aceitável, de modo que você pode considerar que as duas quantidades sejam iguais para fins práticos se a diferença não for maior.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 o valor absoluto da diferença com a diferença aceitável.3. Compare the absolute value of the difference to the acceptable difference.

O exemplo a seguir demonstra a comparação incorreta e correta de dois valores de Double.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))

O exemplo anterior usa o método ToString da estrutura Double para que ele possa especificar uma precisão melhor do que a palavra-chave CStr usa.The previous example uses the ToString method of the Double structure so that it can specify better precision than the CStr keyword uses. O padrão é 15 dígitos, mas o formato "G17" o estende para 17 dígitos.The default is 15 digits, but the "G17" format extends it to 17 digits.

O operador Mod não retorna um resultado precisoMod Operator Does Not Return Accurate Result

Devido à imprecisão do armazenamento de ponto flutuante, o operador Mod pode retornar um resultado inesperado quando pelo menos um dos operandos for de ponto flutuante.Because of the imprecision of floating-point storage, the Mod Operator can return an unexpected result when at least one of the operands is floating-point.

O tipo de dados decimal não usa representação de ponto flutuante.The Decimal Data Type does not use floating-point representation. Muitos números que são inexatos em Single e Double são exatos em Decimal (por exemplo, 0,2 e 0,3).Many numbers that are inexact in Single and Double are exact in Decimal (for example 0.2 and 0.3). Embora a aritmética seja mais lenta em Decimal do que no ponto flutuante, pode valer a pena diminuir o desempenho para obter uma precisão melhor.Although arithmetic is slower in Decimal than in floating-point, it might be worth the performance decrease to achieve better precision.

Para localizar o restante do inteiro de quantidades de ponto flutuanteTo find the integer remainder of floating-point quantities
1. declare variáveis como Decimal.1. Declare variables as Decimal.
2. Use o caractere de tipo literal D para forçar literais a Decimal, caso seus valores sejam muito grandes para o tipo de dados Long.2. Use the literal type character D to force literals to Decimal, in case their values are too large for the Long data type.

O exemplo a seguir demonstra a possível imprecisão de operandos de ponto flutuante.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 método ToString da estrutura Double para que ele possa especificar uma precisão melhor do que a palavra-chave CStr usa.The previous example uses the ToString method of the Double structure so that it can specify better precision than the CStr keyword uses. O padrão é 15 dígitos, mas o formato "G17" o estende para 17 dígitos.The default is 15 digits, but the "G17" format extends it to 17 digits.

Como zeroPointTwo é Double, seu valor de 0,2 é uma fração binária infinitamente repetida com um valor armazenado de 0.20000000000000001.Because zeroPointTwo is Double, its value for 0.2 is an infinitely repeating binary fraction with a stored value of 0.20000000000000001. A divisão 2,0 por essa quantidade produz 9.9999999999999995 com um restante de 0.19999999999999991.Dividing 2.0 by this quantity yields 9.9999999999999995 with a remainder of 0.19999999999999991.

Na expressão para decimalRemainder, o caractere de tipo literal D força os dois operandos a Decimale 0,2 tem uma representação precisa.In the expression for decimalRemainder, the literal type character D forces both operands to Decimal, and 0.2 has a precise representation. Portanto, o operador de Mod produz o restante esperado de 0,0.Therefore the Mod operator yields the expected remainder of 0.0.

Observe que não é suficiente declarar decimalRemainder como Decimal.Note that it is not sufficient to declare decimalRemainder as Decimal. Você também deve forçar os literais a Decimalou usar Double por padrão e decimalRemainder recebe o mesmo valor impreciso como doubleRemainder.You must also force the literals to Decimal, or they use Double by default and decimalRemainder receives the same inaccurate value as doubleRemainder.

O tipo booliano não converte em tipo numérico com precisãoBoolean Type Does Not Convert to Numeric Type Accurately

Os valores de tipo de dados booliano não são armazenados como números e os valores armazenados não devem ser equivalentes aos números.Boolean Data Type values are not stored as numbers, and the stored values are not intended to be equivalent to numbers. Para compatibilidade com versões anteriores, Visual Basic fornece palavras-chave de conversão (função CType, CBool, CInte assim por diante) para converter entre tipos de Boolean e numéricos.For compatibility with earlier versions, Visual Basic provides conversion keywords (CType Function, CBool, CInt, and so on) to convert between Boolean and numeric types. No entanto, outras linguagens às vezes executam essas conversões de forma diferente, assim como os métodos de .NET Framework.However, other languages sometimes perform these conversions differently, as do the .NET Framework methods.

Você nunca deve escrever código que dependa de valores numéricos equivalentes para True e False.You should never write code that relies on equivalent numeric values for True and False. Sempre que possível, você deve restringir o uso de variáveis de Boolean para os valores lógicos para os quais elas foram projetadas.Whenever possible, you should restrict usage of Boolean variables to the logical values for which they are designed. Se você precisar misturar Boolean e valores numéricos, certifique-se de entender o método de conversão que você selecionar.If you must mix Boolean and numeric values, make sure that you understand the conversion method that you select.

Conversão em Visual BasicConversion in Visual Basic

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

Conversão na estruturaConversion in the Framework

O método ToInt32 da classe Convert no namespace System converte True para + 1.The ToInt32 method of the Convert class in the System namespace converts True to +1.

Se você precisar converter um valor de Boolean para um tipo de dados numérico, tenha cuidado com o método de conversão usado.If you must convert a Boolean value to a numeric data type, be careful about which conversion method you use.

O literal de caractere gera erro de compiladorCharacter Literal Generates Compiler Error

Na ausência de qualquer caractere de tipo, Visual Basic pressupõe tipos de dados padrão para literais.In the absence of any type characters, Visual Basic assumes default data types for literals. O tipo padrão para um literal de caractere, entre aspas (" "), é String.The default type for a character literal — enclosed in quotation marks (" ") — is String.

O tipo de dados String não amplia para o tipo de dados char.The String data type does not widen to the Char Data Type. Isso significa que, se você quiser atribuir um literal a uma variável Char, deverá fazer uma conversão de restrição ou forçar o literal para o tipo Char.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.

Para criar um literal char para atribuir a uma variável ou constanteTo create a Char literal to assign to a variable or constant
1. declare a variável ou constante como Char.1. Declare the variable or constant as Char.
2. Coloque o valor do caractere entre aspas (" ").2. Enclose the character value in quotation marks (" ").
3. siga as aspas duplas de fechamento com o caractere de tipo literal C para forçar o literal a Char.3. Follow the closing double quotation mark with the literal type character C to force the literal to Char. Isso será necessário se a opção de verificação de tipo (instrução Option Strict) for One for desejável em qualquer caso.This is necessary if the type checking switch (Option Strict Statement) is On, and it is desirable in any case.

O exemplo a seguir demonstra as atribuições malsucedidas e bem-sucedidas de um literal para uma variável Char.The following example demonstrates both unsuccessful and successful assignments of a literal to a Char variable.

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

Sempre há um risco no uso de conversões redutoras, pois elas podem falhar em tempo de execução.There is always a risk in using narrowing conversions, because they can fail at run time. Por exemplo, uma conversão de String para Char pode falhar se o valor de String contiver mais de um caractere.For example, a conversion from String to Char can fail if the String value contains more than one character. Portanto, é melhor programar para usar o caractere de tipo de C.Therefore, it is better programming to use the C type character.

A conversão da cadeia de caracteres falha em tempo de execuçãoString Conversion Fails at Run Time

O tipo de dados String participa de poucas conversões ampliadas.The String Data Type participates in very few widening conversions. String amplia somente para si mesmo e Object, e somente Char e Char() (uma matriz Char) ampliam para String.String widens only to itself and Object, and only Char and Char() (a Char array) widen to String. Isso ocorre porque String variáveis e constantes podem conter valores que outros tipos de dados não podem conter.This is because String variables and constants can contain values that other data types cannot contain.

Quando a opção de verificação de tipo (instrução Option Strict) é On, o compilador não permite todas as conversões de estreitamento implícitas.When the type checking switch (Option Strict Statement) is On, the compiler disallows all implicit narrowing conversions. Isso inclui aqueles que envolvem String.This includes those involving String. Seu código ainda pode usar palavras-chave de conversão, como CStr e a função CType, que direcionam a .NET Framework para tentar a conversão.Your code can still use conversion keywords such as CStr and CType Function, which direct the .NET Framework to attempt the conversion.

Observação

O erro de conversão de restrição é suprimido para conversões dos elementos em uma coleção de For Each…Next para a variável de controle de loop.The narrowing-conversion error is suppressed for conversions from the elements in a For Each…Next collection to the loop control variable. Para obter mais informações e exemplos, consulte a seção "conversões redutoras" em para cada... Próxima instrução.For more information and examples, see the "Narrowing Conversions" section in For Each...Next Statement.

Restringir a proteção de conversãoNarrowing Conversion Protection

A desvantagem de conversões redutoras é que elas podem falhar em tempo de execução.The disadvantage of narrowing conversions is that they can fail at run time. Por exemplo, se uma variável String contiver algo diferente de "true" ou "false", ela não poderá ser convertida em Boolean.For example, if a String variable contains anything other than "True" or "False," it cannot be converted to Boolean. Se ele contiver caracteres de pontuação, a conversão para qualquer tipo numérico falhará.If it contains punctuation characters, conversion to any numeric type fails. A menos que você saiba que a variável String sempre armazena os valores que o tipo de destino pode aceitar, você não deve tentar uma conversão.Unless you know that your String variable always holds values that the destination type can accept, you should not try a conversion.

Se você precisar converter de String para outro tipo de dados, o procedimento mais seguro é colocar a conversão tentada no bloco try... Capturar... Instrução Finally.If you must convert from String to another data type, the safest procedure is to enclose the attempted conversion in the Try...Catch...Finally Statement. Isso permite que você lide com uma falha de tempo de execução.This lets you deal with a run-time failure.

Matrizes de caracteresCharacter Arrays

Um único Char e uma matriz de elementos Char ampliam para String.A single Char and an array of Char elements both widen to String. No entanto, String não amplia para Char().However, String does not widen to Char(). Para converter um valor de String em uma matriz Char, você pode usar o método ToCharArray da classe System.String.To convert a String value to a Char array, you can use the ToCharArray method of the System.String class.

Valores sem significadoMeaningless Values

Em geral, os valores de String não são significativos em outros tipos de dados, e a conversão é altamente artificial e perigosa.In general, String values are not meaningful in other data types, and conversion is highly artificial and dangerous. Sempre que possível, você deve restringir o uso de variáveis de String para as sequências de caracteres para as quais elas foram projetadas.Whenever possible, you should restrict usage of String variables to the character sequences for which they are designed. Você nunca deve escrever código que dependa de valores equivalentes em outros tipos.You should never write code that relies on equivalent values in other types.

Consulte tambémSee also