Solucionando problemas de Tipos de Dados

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 duplo (Visual Basic)), lembre-se que eles são armazenados como frações binárias.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.

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 decimais (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 booleanos (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 (CType Function,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 Caractere tipo de dados (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 (Opção declaração estrito) é On,e em qualquer caso, isto é desejável.

O exemplo a seguir demonstra atribuições bem e malsucedidas de um literal para uma variável Char.

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

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.

Conversão de Sequência de Caracteres Falha em Tempo de Execução

The Tipo de dados de sequência de caracteres (Visual Basic) participa muito poucos conversões de expansão. String amplia a mesmo e Objecte somente Char e Char() (um Char matriz) ampliar 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 (Opção declaração estrito) é 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 CType Function, que direciona o .NET Framework a tentar a conversão.

Observação:

O erro de conversão de restrição é 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"For each... Next demonstrativo (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 Try... Catch... Finally demonstrativo (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 System.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 sequencia 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

Conceitos

Tipos de dados no Visual Basic

Caracteres de Tipo.

Programação Sem-Tipos no Visual Basic

Tipos de Dados São Tipos .NET Framework

Uso eficiente de tipos de dados

Referência

Resumo de tipo de dados (Visual Basic)

Funções de conversão de tipo 

Outros recursos

Implementação de tipos de dados

Conversões de Tipo no Visual Basic

Date

History

Motivo

Julho de 2008

Adicionar uma observação sobre como restringir as conversões e For Each…Next.

Comentários do cliente.