Compartilhar via


Solucionando problemas de tipos de dados (Visual Basic)

Essa página lista alguns problemas comuns que podem ocorrer quando você realiza operações com tipos de dado intrínsecos.

Não Comparar Expressões em Ponto Flutuante (Floating-Point) como Igual

Quando você trabalha com números de ponto flutuante (Tipo de dados único (Visual Basic) e Tipo de dados double (Visual Basic)), lembre-se que eles são armazenados como frações binárias. 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 números inteiros). 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.

Devido a essa imprecisão, você não pode depender de resultados exatos quando opera com valores de ponto flutuante. Em particular, dois valores que são, teoricamente, iguais podem ter representações ligeiramente diferentes.

Para comparar as quantidades de ponto flutuante

  1. Calcule a valor absoluto de seu diferença usando o método Abs da classe Math no namespace System.

  2. Determine uma diferença máxima aceitável, de forma que você pode considerar as duas quantidades como iguais para fins práticos se a diferença não for maior.

  3. Compare o valor absoluto da diferença com a diferença aceitável.

O exemplo a seguir demonstra comparações correta e incorreta entre dois valores 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))

O exemplo anterior usa o método ToString da estrutura Double para que ele possa especificar uma precisão melhor do que aquela que a palavra-chave CStr usa. O padrão é 15 dígitos, mas o formato "G17" estende a até 17 dígitos.

Operador Mod Não Retorna Resultados Precisos

Devido à imprecisão de armazenamento de ponto flutuante, o Operador Mod (Visual Basic) pode retornar um resultado inesperado quando pelo menos um dos operandos for ponto flutuante.

Tipo de dados decimal (Visual Basic) não usa representação de ponto flutuante. Muitos números que são inexatos em Single e Double são exatos em Decimal (por exemplo 0.2 e 0,3). Embora a aritmética seja mais lenta em Decimal do que em ponto flutuante, talvez valha a pena a redução de desempenho para obter melhor precisão.

Para localizar o resto inteiro de quantidades de ponto flutuante

  1. Declare as variáveis como Decimal.

  2. Use o caractere de tipo literal D para forçar literais a Decimal, caso os valores sejam muito grandes para o tipo de dado Long.

O exemplo a seguir demonstra a imprecisão potencial de operandos em ponto flutuante.

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 aquela que a palavra-chave CStr usa. O padrão é 15 dígitos, mas o formato "G17" estende a até 17 dígitos.

Como zeroPointTwo é Double,seu valor 0,2 é uma fração binária de repetição infinita com um valor armazenado de 0.20000000000000001. A divisão 2.0 por essa quantidade produz 9.9999999999999995 com resto 0.19999999999999991.

Em uma expressão para decimalRemainder, o caracter de tipo literal D força ambos os operandos para Decimal, e 0.2 tem uma representação exata. Portanto, o operador Mod produz o resto 0.0 esperado.

Observe que é não suficiente declarar decimalRemainder como Decimal. Você também deve forçar os literais para que sejam Decimal, ou eles usam Double por padrão e decimalRemainder recebe o mesmo valor doubleRemainder impreciso.

Tipo Booleano Não Cconverte para Tipo Numérico com Precisão

Valores Tipo de dados booliano (Visual Basic) não são armazenados como números, e não se espera que os valores armazenados sejam equivalentes a números. Para compatibilidade com versões anteriores, Visual Basic fornece conversão de palavras-chave (Função CType (Visual Basic),CBool,CInt, e assim por diante) para converter entre Boolean e tipos numéricos. No entanto, outras linguagens, às vezes, executam essas conversões de maneira diferente, como fazem os métodos .NET Framework.

Você nunca deve escrever um código que dependa de valores numéricos equivalentes para True e False. Sempre que possível, você deve restringir uso de variáveis Boolean para os valores lógicos para o quais elas são criadas. Se você deve combinar Boolean e valores numéricos, certifique-se que você entende o método de conversão que você selecionar.

Conversão em Visual Basic

Quando você usar as palavras-chave de conversão CType ou CBool para converter tipos de dados numérico para Boolean,0 se torna False e todos os outros valores tornam-se True. Quando você converte valores Boolean para tipos numéricos usando as palavras-chave de conversão, False se torna 0 e True torna-se -1.

Conversão no Framework

O método ToInt32 da classe Convert no namespace System converte True para + 1.

Se você deve converter um valor Boolean para um tipo de dados numérico, tome cuidado sobre que método de conversão usar.

Caractere Literal Gera Erro do Compilador

Na ausência de qualquer caracteres de tipo, Visual Basic assume tipo de dados padrão para literais. O tipo padrão de um caractere literal — entre aspas (" ") — é String.

O tipo de dados String não amplia para o Tipo de dados Char (Visual Basic). Isso significa que se você desejar atribuir um literal para uma variável Char, você deve fazer uma conversão de restrição ou forçar o literal para o tipo Char.

Para criar um literal Char para atribuir a uma variável ou constante

  1. Declare a variável ou constante como Char.

  2. Coloque o valor de caracteres entre aspas (" ").

  3. Siga as aspas duplas de fechamento do caracter de tipo literal C para forçar o literal para Char. Isso é necessário se a verificação de tipo muda (Instrução Option Strict) é On,e em qualquer caso, isto é desejável.

O exemplo a seguir demonstra atribuições bem e mal sucedidas de um literal para uma variável 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")

Há sempre um risco ao usar conversões redutoras, pois elas podem falhar em tempo de execução. Por exemplo, uma conversão de String em Char pode falhar se o valor String contiver mais de um caractere. Portanto, ele é uma técnica de programação melhor usar o caracter de tipo C.

Falha na conversão de cadeia de caracteres em tempo de execução

O Tipo de dados da cadeia 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. Isso ocorre porque variáveis e constantes String podem conter valores que outros tipos de dados não podem conter.

Quando o verificação de tipo muda (Instrução Option Strict) é On, o compilador proíbe todos as conversões redutoras implícitas. Isso inclui aquelas envolvendo String. Seu código pode ainda usar conversão de palavras-chave, como CStr e Função CType (Visual Basic), que direciona o .NET Framework a tentar a conversão.

Dica

O erro de conversão narrowing é suprimido para conversões de elementos em um For Each…Next coleção para a variável de controle de loop.Para obter mais informações e exemplos, consulte a seção "Estreitando conversões" Instrução For Each...Next (Visual Basic).

Restringir a Proteção de Conversão

A desvantagem de conversões redutoras é que eles podem falhar em tempo de execução. Por exemplo, se uma variável String contiver algo diferente de "True" ou "False", ela não pode ser convertido em Boolean. Se ele contiver caracteres de pontuação, a conversão em qualquer tipo numérico falhará. A menos que você saiba que a variável String sempre contém valores que o tipo de destino pode aceitar, você não deve tentar uma conversão.

Se você deve converter de String para outro tipo de dados, o procedimento mais seguro é cercar a tentativa de conversão com Instrução Try...Catch...Finally (Visual Basic). Isso permite que você lide com uma falha em tempo de execução.

Matrizes de Caracteres

Um único Char e uma matriz de elementos Char ampliam para String. No entanto, String não amplia para Char(). Para converter um valor String em uma matriz Char, você pode usar o método ToCharArray da classe String.

Valores Sem Significado

Em geral, os valores String não são significativos em outros tipos de dados, e a conversão é perigosa e altamente artificial. Sempre que possível, você deve restringir o uso de variáveis String a seqüencia de caracteres para as quais elas são criadas. Você nunca deve escrever código que se baseie em valores equivalentes em outros tipos.

Consulte também

Referência

Resumo do tipo de dados (Visual Basic)

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

Conceitos

Tipos de dados no Visual Basic

Caracteres de tipo (Visual Basic)

Tipos de valor e referência

Uso eficiente de tipos de dados (Visual Basic)

Outros recursos

Conversões de tipo no Visual Basic