2008-10-24 24 views
8

tengo problemas para comparar 2 dobles en Excel VBACompare doble en VBA problema precisión

suponer que tengo el siguiente código

Dim a as double 
Dim b as double 
a = 0.15 
b = 0.01 

Después de unas manipulaciones en b, b es ahora igual a 0,6

sin embargo, la imprecisión relacionada con el tipo de datos doble me da dolor de cabeza debido a

if a = b then 
//this will never trigger 
end if 

¿Sabes cómo puedo eliminar la imprecisión final en el tipo doble?

Respuesta

13

No se pueden comparar valores de punto flotante para la igualdad. Consulte este artículo en "Comparing floating point numbers" para ver una discusión sobre cómo manejar el error intrínseco.

No es tan simple como comparar con un margen de error constante a menos que sepa con certeza cuál es el rango absoluto de los flotadores de antemano.

+1

Por otra referencia se puede extraer http://msdn.microsoft.com/en-us/ library/ae382yt8 (VS.80) .aspx – ZCHudson

3

Nunca es sabio comparar dobles en igualdad.

Algunos valores decimales se asignan a varias representaciones de coma flotante. Entonces uno 0.6 no siempre es igual al otro 0.6.

Si restamos una de la otra, es probable que obtengamos algo así como 0.00000000051.

Ahora podemos definir la igualdad como tener una diferencia menor que un cierto margen de error.

1

Como se ha señalado, muchos números decimales no se pueden representar precisamente como tipos tradicionales de coma flotante. Dependiendo de la naturaleza de su espacio problemático, es mejor que utilice el tipo Decimal VBA que puede representar números decimales (base 10) con precisión perfecta hasta un cierto punto decimal. Esto a menudo se hace para representar dinero, por ejemplo, donde a menudo se desea una precisión decimal de 2 dígitos.

Dim a as Decimal 
Dim b as Decimal 
a = 0.15 
b = 0.01 
+0

¿El decimal está disponible en vba? Creo que debes declarar como variante y luego convertir a decimal a través de Cdec (myVar). –

1

El tipo de datos de moneda puede ser una buena alternativa. Maneja números relativamente grandes con precisión fija de cuatro dígitos.

3

si se va a hacer esto ....

Dim a as double 
Dim b as double 
a = 0.15 
b = 0.01 

es necesario agregar la función de ronda en su instrucción IF así ...

If Round(a,2) = Round(b,2) Then 
    //code inside block will now trigger. 
    End If 

Véase también here for additional Microsoft reference.

2

Aquí es una función simple que escribí:

Function dblCheckTheSame(number1 As Double, number2 As Double, Optional Digits As Integer = 12) As Boolean 

If (number1 - number2)^2 < (10^-Digits)^2 Then 
    dblCheckTheSame = True 
Else 
    dblCheckTheSame = False 
End If 

End Function 

llamada con:

MsgBox dblCheckTheSame(1.2345, 1.23456789) 
MsgBox dblCheckTheSame(1.2345, 1.23456789, 4) 
MsgBox dblCheckTheSame(1.2345678900001, 1.2345678900002) 
MsgBox dblCheckTheSame(1.2345678900001, 1.2345678900002, 14) 
Cuestiones relacionadas