Question

J'ai des difficultés à comparer 2 doubles dans Excel VBA

supposons que j'ai le code suivant

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

Après quelques manipulations sur b, b est maintenant égal à 0,6

Cependant, l'imprécision liée au type de données double me donne mal à la tête parce que

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

Savez-vous comment je peux supprimer l’imprécision de fuite sur le type double?

Était-ce utile?

La solution

Vous ne pouvez pas comparer les valeurs à virgule flottante pour l'égalité. Voir cet article sur " Comparaison des flottants nombres " pour une discussion sur la façon de gérer l'erreur intrinsèque.

Il n’est pas aussi simple que de comparer à une marge d’erreur constante à moins de savoir avec certitude quelle est la plage absolue des flotteurs.

Autres conseils

si vous allez faire cela ....

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

vous devez ajouter la fonction round dans votre déclaration IF comme ceci ...

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

Voir aussi ici pour une référence Microsoft supplémentaire .

Il n’est jamais sage de comparer les doubles en égalité.

Certaines valeurs décimales correspondent à plusieurs représentations en virgule flottante. Donc, un 0.6 n'est pas toujours égal à l'autre 0.6.

Si nous soustrayons l'un de l'autre, nous obtenons probablement quelque chose comme 0.00000000051.

Nous pouvons maintenant définir l'égalité comme ayant une différence inférieure à une certaine marge d'erreur.

Voici une fonction simple que j'ai écrite:

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

Appelez-le avec:

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)

Comme il a été souligné, de nombreux nombres décimaux ne peuvent pas être représentés avec précision sous forme de types à virgule flottante traditionnels. En fonction de la nature de votre espace de problèmes, il peut être préférable d’utiliser le type VBA décimal, qui peut représenter des nombres décimaux (base 10) avec une précision parfaite jusqu’à un certain point décimal. Ceci est souvent fait pour représenter de l'argent, par exemple lorsqu'une précision décimale à 2 chiffres est souvent souhaitée.

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

Le type de données Currency peut être une bonne alternative. Il gère des nombres relativement importants avec une précision fixe à quatre chiffres.

Travail-a-tour ?? Pas sûr que cela réponde à tous les scénarios, mais j'ai rencontré un problème en comparant les valeurs doubles arrondies dans VBA. Lorsque j'ai comparé des nombres qui semblaient identiques après l'arrondissement, VBA a déclenché la valeur false dans une instruction if-then compare. Mon correctif était d’exécuter deux conversions, d’abord doubler en chaîne, puis chaîne à doubler, puis faire la comparaison.

Exemple simulé Je n'ai pas enregistré les chiffres exacts à l'origine de l'erreur mentionnée dans ce message, et les montants de mon exemple ne déclenchent pas le problème actuellement et sont destinés à représenter le type de problème.

 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top