Domanda

Ho difficoltà a confrontare 2 doppie in Excel VBA

supponi di avere il seguente codice

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

Dopo alcune manipolazioni su b, b ora è uguale a 0,6

tuttavia l'imprecisione relativa al doppio tipo di dati mi dà mal di testa perché

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

Sai come posso rimuovere l'imprecisione finale sul doppio tipo?

È stato utile?

Soluzione

Non è possibile confrontare i valori in virgola mobile per l'uguaglianza. Consulta questo articolo su " Confronto di virgola mobile numeri " per una discussione su come gestire l'errore intrinseco.

Non è semplice come confrontarlo con un margine di errore costante a meno che non si sappia con certezza quale sia la gamma assoluta dei float.

Altri suggerimenti

se hai intenzione di farlo ....

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

devi aggiungere la funzione round nell'istruzione IF in questo modo ...

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

Vedi anche qui per ulteriori riferimenti Microsoft .

Non è mai saggio confrontare i doppi sull'uguaglianza.

Alcuni valori decimali sono associati a diverse rappresentazioni in virgola mobile. Quindi uno 0.6 non è sempre uguale all'altro 0.6.

Se sottraggiamo l'uno dall'altro, probabilmente otteniamo qualcosa come 0.00000000051.

Ora possiamo definire l'uguaglianza come avere una differenza minore di un certo margine di errore.

Ecco una semplice funzione che ho scritto:

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

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

Come è stato sottolineato, molti numeri decimali non possono essere rappresentati esattamente come tipi tradizionali a virgola mobile. A seconda della natura del tuo spazio problematico, potresti stare meglio usando il tipo VBA decimale che può rappresentare numeri decimali (base 10) con precisione perfetta fino a un certo punto decimale. Questo viene spesso fatto per rappresentare denaro, ad esempio quando si desidera spesso la precisione decimale a 2 cifre.

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

Il tipo di dati Valuta può essere una buona alternativa. Gestisce numeri relativamente grandi con una precisione fissa di quattro cifre.

Il lavoro-a-tutto l'?? Non sono sicuro se questo risponderà a tutti gli scenari, ma ho riscontrato un problema nel confrontare valori doppi arrotondati in VBA. Quando ho confrontato con numeri che sembravano essere identici dopo l'arrotondamento, VBA avrebbe attivato false in un'istruzione if-then compare. La mia correzione era di eseguire due conversioni, prima il doppio in stringa, quindi la stringa in doppio, quindi fare il confronto.

Esempio simulato Non ho registrato i numeri esatti che hanno causato l'errore menzionato in questo post e gli importi nel mio esempio non attivano il problema attualmente e sono destinati a rappresentare il tipo di problema.

 Sub Test_Rounded_Numbers()

      Dim Num1 As Double

      Dim Num2 As Double

      Let Num1 = 123.123456789

      Let Num2 = 123.123467891

      Let Num1 = Round(Num1, 4) '123.1235


      Let Num2 = Round(Num2, 4) '123.1235

      If Num1 = Num2 Then

           MsgBox "Correct Match, " & Num1 & " does equal " & Num2
      Else
           MsgBox "Inccorrect Match, " & Num1 & " does not equal " & Num2
      End If

      'Here it would say that "Inccorrect Match, 123.1235 does not equal 123.1235."

 End Sub

 Sub Fixed_Double_Value_Type_Compare_Issue()

      Dim Num1 As Double

      Dim Num2 As Double

      Let Num1 = 123.123456789

      Let Num2 = 123.123467891

      Let Num1 = Round(Num1, 4) '123.1235


      Let Num2 = Round(Num2, 4) '123.1235

      'Add CDbl(CStr(Double_Value))
      'By doing this step the numbers
      'would trigger if they matched
      '100% of the time

      If CDbl(CStr(Num1)) = CDbl(CStr(Num2)) Then

           MsgBox "Correct Match"
      Else
           MsgBox "Inccorrect Match"

      End If

      'Now it says Here it would say that "Correct Match, 123.1235 does equal 123.1235."
 End Sub
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top