2008-10-24 12 views
8

mam kłopot porównując 2 Dwukrotnie w Excel VBAPorównaj dwukrotnie w VBA precyzji problemu

załóżmy, że mam następujący kod

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

Po kilku manipulacji na B, B jest równe 0,6

jednak nieścisłości związane z podwójnym typu danych daje mi ból głowy, ponieważ

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

Czy wiesz, w jaki sposób mogę usunąć niedokładność końcową w podwójnym typie?

Odpowiedz

13

Nie można porównywać wartości zmiennoprzecinkowych dla równości. Zobacz ten artykuł na temat "Comparing floating point numbers", aby omówić sposób radzenia sobie z wewnętrznym błędem.

To nie jest tak proste, jak porównanie ze stałym marginesem błędu, chyba że wiesz na pewno, jaki jest bezwzględny zakres pływaków.

+1

Dla innego odniesienia można sprawdzić http://msdn.microsoft.com/en-us/ biblioteka/ae382yt8 (VS.80) .aspx – ZCHudson

3

Nigdy nie jest mądre porównywać podwójne na równość.

Niektóre wartości dziesiętne są odwzorowane na kilka reprezentacji zmiennoprzecinkowych. Tak więc 0,6 nie zawsze jest równe 0,6.

Jeśli odejmujemy jedno od drugiego, prawdopodobnie otrzymujemy coś w rodzaju 0.00000000051.

Możemy teraz zdefiniować równość jako różnicę mniejszą niż określony margines błędu.

1

Jak już wskazano, wiele liczb dziesiętnych nie może być przedstawianych dokładnie jako tradycyjne typy zmiennoprzecinkowe. Zależnie od rodzaju miejsca, w którym występuje problem, lepszym rozwiązaniem może być użycie dziesiętnego typu VBA, który może reprezentować liczby dziesiętne (podstawa 10) z idealną precyzją do określonej wartości dziesiętnej. Często odbywa się to w celu przedstawienia pieniędzy, na przykład, gdy często jest pożądana dwucyfrowa dokładność dziesiętna.

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

Czy w systemie vba dostępny jest dziesiętny? Myślę, że musisz zadeklarować jako wariant, a następnie rzutować na dziesiętne przez Cdec (myVar). –

1

Typ danych walutowych może być dobrą alternatywą. Obsługuje stosunkowo duże liczby ze stałą czterocyfrową precyzją.

3

jeśli masz zamiar to zrobić ....

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

trzeba dodać funkcję okrągły w wyciągu Jeśli podoba to ...

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

Zobacz również here for additional Microsoft reference.

2

Oto prosta funkcja pisałem:

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 

połączenia go z:

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)