Solucionar problemas de tipos de datos (Visual Basic)
Esta página muestra algunos problemas comunes que pueden aparecer al realizar operaciones en tipos de datos intrínsecos.
Las expresiones de punto flotante no se comparan como iguales
Cuando trabaje con números de punto flotante (Single (Tipo de datos, Visual Basic) y Double (Tipo de datos, Visual Basic)), tenga en cuenta que se almacenan como fracciones binarias. Esto significa que no pueden contener una representación exacta de ninguna cantidad que no sea una fracción binaria (con el formato k / (2 ^ n) donde k y n son números enteros). Por ejemplo, 0,5 (= 1/2) y 0,3125 (= 5/16) se pueden almacenar como valores precisos, mientras que 0,2 (= 1/5) y 0,3 (= 3/10) sólo pueden se aproximaciones.
Debido a esta imprecisión, no puede confiar en resultados exactos cuando trabaje en valores de punto flotante. Concretamente, dos valores que son teóricamente iguales podrían tener representaciones ligeramente distintas.
Para comparar cantidades de punto flotante |
|
En el ejemplo siguiente se muestran comparaciones incorrectas y correctas de dos 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))
En el ejemplo anterior se usa el método ToString de la estructura Double para que pueda especificar una mayor precisión que la utilizada por la palabra clave CStr. El valor predeterminado es de 15 dígitos, pero el formato "G17" lo amplía a 17 dígitos.
El operador Mod no devuelve un resultado preciso
Debido al imprecisión de almacenamiento con punto flotante, el Mod (Operador, Visual Basic) puede devolver un resultado inesperado cuando al menos uno de los operandos es de punto flotante.
El Decimal (Tipo de datos, Visual Basic) no utiliza la representación en punto flotante. Muchos números que son inexactos en formato Single y Double son exactos en el formato Decimal (por ejemplo 0,2 y 0,3). Aunque las operaciones aritméticas se realizan más lentamente en formato Decimal que con punto flotante, podría merecer la pena perder rendimiento para conseguir una mayor precisión.
Para buscar el resto entero de cantidades de punto flotante |
|
En el ejemplo siguiente se muestra la imprecisión potencial de los operandos de punto flotante.
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))
En el ejemplo anterior se usa el método ToString de la estructura Double para que pueda especificar una mayor precisión que la utilizada por la palabra clave CStr. El valor predeterminado es de 15 dígitos, pero el formato "G17" lo amplía a 17 dígitos.
Dado que zeroPointTwo es Double, su valor para 0,2 es una fracción binaria infinitamente repetitiva con un valor almacenado de 0,20000000000000001. Al dividir 2,0 por esta cantidad, se obtiene 9,9999999999999995 con un resto de 0,19999999999999991.
En la expresión de decimalRemainder, el carácter de tipo literal D obliga a que ambos operandos sean Decimal, y 0,2 tenga una representación precisa. Por consiguiente el operador Mod produce el resto esperado de 0,0.
Tenga en cuenta que no basta con declarar decimalRemainder como Decimal. También debe forzar los valores literales a Decimal o a que su valor predeterminado sea Double y decimalRemainder reciba el mismo valor inexacto que doubleRemainder.
El tipo booleano no convierte con precisión al tipo numérico
Los valores Boolean (Tipo de datos, Visual Basic) no se almacenan como números y los valores almacenados no se consideran equivalentes a números. Para la compatibilidad con versiones anteriores, Visual Basic proporciona las palabras clave de conversión (CType (Función) (Visual Basic), CBool, CInt, etc.) para convertir entre Boolean y los tipos numéricos. Sin embargo, en ocasiones otros lenguajes realizan de manera diferente estas conversiones, como ocurre con los métodos de .NET Framework.
No debe escribir código que se base en los valores numéricos equivalentes de True y False. Siempre que sea posible, debe restringir el uso de variables Boolean a los valores lógicos para los que se han diseñado. Si debe mezclar valores Boolean y numéricos, asegúrese de que entiende el método de conversión que selecciona.
Conversión en Visual Basic
Cuando utilice la conversión CType o CBool para convertir tipos de datos numéricos en Boolean, 0 se convierte en False y todos los demás valores en True. Al convertir valores Boolean en tipos numéricos usando las palabras clave de conversión, False se convierte en 0 y True en -1.
Conversión en Framework
El método ToInt32 de la clase Convert del espacio de nombres System convierte True en +1.
Si necesita convertir un valor Boolean en un tipo de datos numérico, tenga cuidado al elegir el método de conversión usado.
El carácter literal genera un error del compilador
En ausencia de caracteres de tipo, Visual Basic presupone los tipos de datos predeterminados para los valores literales. El tipo predeterminado para un literal de carácter, incluido entre comillas (" "), es String.
El tipo de datos String no amplía al Char (Tipo de datos, Visual Basic). Esto significa que, si desea asignar un literal a una variable Char, debe realizar una conversión de restricción para forzar a que el valor literal sea del tipo Char.
Para crear un literal Char para asignarlo a una variable o constante |
|
El ejemplo siguiente muestra asignaciones incorrectas y correctas de un valor literal a una variable 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")
Siempre existe un riesgo en la utilización de conversiones de restricción, porque se pueden producir errores en tiempo de ejecución. Por ejemplo, se puede producir un error en una conversión de String a Char si el valor String contiene más de un carácter. Por consiguiente, es mejor programar para que se utilice el carácter de tipo C.
La conversión de cadenas produce errores en tiempo de ejecución
El String (Tipo de datos, Visual Basic) toma parte en muy pocas conversiones de ampliación. String solo se amplía a sí mismo y a Object, y solo Char y Char() (matriz de Char) amplían a String. Esto es así porque las variables y constantes String pueden contener valores que no pueden contener otros tipos de datos.
Cuando el modificador de comprobación del tipo (Option Strict (Instrucción)) está On, el compilador deniega todas las conversiones de restricción implícitas. Esto incluye las que implican String. El código todavía puede usar palabras clave de conversión como CStr y la CType (Función) (Visual Basic), que indican a .NET Framework que intente realizar la conversión.
Nota |
---|
El error de la conversión de restricción se suprime en las conversiones de los elementos de una colección For Each…Next a la variable de control del bucle.Para obtener más información y ejemplos, consulte la sección "Conversiones de restricción" en Instrucción For Each...Next (Visual Basic). |
Protección de conversión de restricción
El inconveniente de las conversiones de restricción es que pueden producir errores en tiempo de ejecución. Por ejemplo, si una variable String contiene un valor distinto de "True" o "False", no se puede convertir a Boolean. Si contiene caracteres de puntuación, se produce un error al convertir en cualquier tipo numérico. A menos que sepa que la variable String siempre contiene valores aceptados por el tipo de destino, no debería intentar la conversión.
Si necesita convertir de String a otro tipo de datos, el procedimiento más seguro consiste en incluir la conversión que intenta realizar en la Instrucción Try...Catch...Finally (Visual Basic). Esto le permite tratar los errores en tiempo de ejecución.
Matrices de caracteres
Un único carácter Char y una matriz de elementos Char se amplían a String. Sin embargo, String no amplia a Char(). Para convertir un valor String en una matriz Char, puede utilizar el método ToCharArray de la clase String.
Valores sin sentido
En general, los valores String no tienen ningún sentido en otros tipos de datos y la conversión resulta muy artificial y peligrosa. Siempre que sea posible, debe restringir el uso de variables String a las secuencias de caracteres para las que están diseñadas. Nunca debería escribir código basándose en los valores equivalentes en otros tipos.
Vea también
Referencia
Resumen de tipos de datos (Visual Basic)
Funciones de conversión de tipos (Visual Basic)
Conceptos
Tipos de datos en Visual Basic
Caracteres de tipo (Visual Basic)
Tipos de valor y tipos de referencia
Uso eficiente de tipos de datos (Visual Basic)