Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Esta página lista alguns problemas comuns que podem ocorrer quando você executa operações em tipos de dados intrínsecos.
expressões Floating-Point não são comparadas como iguais
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. Isso significa que eles não podem conter 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). 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 contar com resultados exatos quando opera em valores de ponto flutuante. Em particular, dois valores teoricamente iguais podem ter representações ligeiramente diferentes.
| Para comparar quantidades de ponto flutuante |
|---|
| 1. Calcule o valor absoluto de sua diferença usando o Abs método da Math classe no System namespace. 2. Determine uma diferença máxima aceitável, de modo que você possa considerar as duas quantidades 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 a comparação incorreta e correta de dois Double valores.
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 ToString método da estrutura para Double que ele possa especificar melhor precisão do que a CStr palavra-chave usa. O padrão é 15 dígitos, mas o formato "G17" estende-o para 17 dígitos.
O operador Mod não retorna o resultado preciso
Devido à imprecisão do armazenamento de ponto flutuante, o Operador Mod pode retornar um resultado inesperado quando pelo menos um dos operandos é ponto flutuante.
O Tipo de Dados Decimal não usa representação de ponto flutuante. Muitos números que são inexact e SingleDouble são exatos ( Decimal por exemplo, 0,2 e 0,3). Embora a aritmética seja mais lenta do que no Decimal ponto flutuante, pode valer a pena diminuir o desempenho para obter melhor precisão.
| Para localizar o restante inteiro de quantidades de ponto flutuante |
|---|
1. Declarar variáveis como Decimal.2. Use o caractere D de tipo literal para forçar literais, Decimalcaso seus valores sejam muito grandes para o Long tipo de dados. |
O exemplo a seguir demonstra a imprecisão potencial de operandos de 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 ToString método da estrutura para Double que ele possa especificar melhor precisão do que a CStr palavra-chave usa. O padrão é 15 dígitos, mas o formato "G17" estende-o para 17 dígitos.
Por zeroPointTwo isso Double, seu valor para 0,2 é uma fração binária infinitamente recorrente com um valor armazenado de 0,2000000000000000001. Dividir 2,0 por essa quantidade produz 9,9999999999999999995 com um restante de 0,1999999999999999999991.
Na expressão para decimalRemainder, o caractere D de tipo literal força ambos os operandos a Decimal, e 0.2 tem uma representação precisa. Portanto, o Mod operador produz o restante esperado de 0,0.
Observe que não é suficiente declarar decimalRemainder como Decimal. Você também deve forçar os literais para Decimal, ou eles usam Double por padrão e decimalRemainder recebe o mesmo valor impreciso que doubleRemainder.
Tipo booliano não converte em tipo numérico com precisão
Os valores de tipo de dados booliano não são armazenados como números e os valores armazenados não se destinam a serem equivalentes a números. Para compatibilidade com versões anteriores, o Visual Basic fornece palavras-chave de conversão (Operador CBoolCType e CIntassim por diante) para converter tipos entre Boolean e numéricos. No entanto, outras linguagens às vezes executam essas conversões de forma diferente, assim como os métodos do .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 o uso de Boolean variáveis aos valores lógicos para os quais elas são projetadas. Se você precisar misturar Boolean valores numéricos, certifique-se de entender o método de conversão selecionado.
Conversão no Visual Basic
Quando você usa as CType palavras-chave ou CBool conversão para converter tipos Booleande dados numéricos False em , 0 se torna e todos os outros valores se tornam True. Quando você converte Boolean valores em tipos numéricos usando as palavras-chave de conversão, False torna-se 0 e True torna-se -1.
Conversão na Estrutura
O ToInt32 método da Convert classe no System namespace é convertido True em +1.
Se você precisar converter um Boolean valor em um tipo de dados numérico, tenha cuidado com qual método de conversão você usa.
O literal de caractere gera erro do compilador
Na ausência de caracteres de qualquer tipo, o Visual Basic pressupõe tipos de dados padrão para literais. O tipo padrão para um literal de caractere — entre aspas (" ") — é String.
O String tipo de dados não é ampliado para o tipo de dados Char. Isso significa que, se você quiser atribuir um literal a uma Char variável, deverá fazer uma conversão de restrição ou forçar o literal para o Char tipo.
| Para criar um literal char para atribuir a uma variável ou constante |
|---|
1. Declare a variável ou a constante como Char.2. Coloque o valor do caractere entre aspas ( " ").3. Siga a aspa dupla de fechamento com o caractere C de tipo literal para forçar o literal a Char. Isso é necessário se o comutador de verificação de tipo (Instrução Opção Estrita) for On, e é desejável em qualquer caso. |
O exemplo a seguir demonstra atribuições malsucedidas e bem-sucedidas de um literal para uma Char variável.
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 em usar conversões de restrição, pois elas podem falhar em tempo de execução. Por exemplo, uma conversão de String para Char pode falhar se o String valor contiver mais de um caractere. Portanto, é melhor programar para usar o caractere de C tipo.
A conversão de cadeia de caracteres falha em tempo de execução
O Tipo de Dados de Cadeia de Caracteres participa de pouquíssimas conversões de ampliação.
String amplia apenas para si mesmo e Object, e somente Char e Char() (uma Char matriz) amplia para String. Isso ocorre porque String variáveis e constantes podem conter valores que outros tipos de dados não podem conter.
Quando a opção de verificação de tipo (Option Strict Statement) é On, o compilador não permite todas as conversões de restrição implícitas. Isso inclui aqueles que envolvem String. Seu código ainda pode usar palavras-chave de conversão, como CStr e Operador CType, que direcionam o .NET Framework para tentar a conversão.
Observação
O erro de conversão de restrição é suprimido para conversões dos elementos em uma For Each…Next coleção para a variável de controle de loop. Para obter mais informações e exemplos, consulte a seção "Limitando conversões" em For Each... Próxima instrução.
Proteção de conversão de restrição
A desvantagem de restringir conversões é que elas podem falhar em tempo de execução. Por exemplo, se uma String variável contiver algo diferente de "True" ou "False", ela não poderá ser convertida Booleanem . Se ele contiver caracteres de pontuação, a conversão em qualquer tipo numérico falhará. A menos que você saiba que sua String variável sempre contém valores que o tipo de destino pode aceitar, você não deve tentar uma conversão.
Se você precisar converter de outro tipo de String dados, o procedimento mais seguro será colocar a tentativa de conversão no Try... Pegar... Instrução Finally. Isso permite que você lide com uma falha em tempo de execução.
Matrizes de caracteres
Um único Char e uma matriz de Char elementos são ampliados para String. No entanto, String não é ampliado para Char(). Para converter um String valor em uma Char matriz, você pode usar o ToCharArray método da System.String classe.
Valores sem sentido
Em geral, String os valores não são significativos em outros tipos de dados e a conversão é altamente artificial e perigosa. Sempre que possível, você deve restringir o uso de String variáveis às sequências de caracteres para as quais elas são projetadas. Você nunca deve escrever um código que dependa de valores equivalentes em outros tipos.