Imprécision/Erreur de Calcul par VBA avec ROUND

_Thierry

XLDnaute Barbatruc
Repose en paix
Bonjour à tous et toutes

Pour mon 886ème post du Forum XLD New Generation ce sera ma première question !

En fait je me trouve confronté à une incohérence de calcul avec la fonction Excel 'ARRONDI' et la même à travers VBA.

Pour mieux figurer mon problème, j'ai mis en fichier joint les montants et les dates respectives pour ce calculs avec les Formules Excel comparées à celles rédigée en VBA...

Lors de l'utilisation de 'ROUND' en VBA j'ai une erreur de calcul.

Quelqu'un aurait-il déjà été confronté à un truc de ce genre ?

Par avance merci

@+Thierry [file name=VBA-Round-Wrong-Calculation_20050510160656.zip size=8261]http://www.excel-downloads.com/components/com_simpleboard/uploaded/files/VBA-Round-Wrong-Calculation_20050510160656.zip[/file]
 

Pièces jointes

  • VBA-Round-Wrong-Calculation_20050510160656.zip
    8.1 KB · Affichages: 50

MichelXld

XLDnaute Barbatruc
bonjour cher Thierry

effectivement c'est curieux

Round((BaseAmount * InterestRate) / 100 * _
((CDate(DateStop) - CDate(DateStart)) / DayPerYear), 2)


renvoie 1409,37


par contre

Application.WorksheetFunction.Round((BaseAmount * InterestRate) / 100 * _
((CDate(DateStop) - CDate(DateStart)) / DayPerYear), 2)


renvoie 1409,38 , comme la formule de la cellule B15

(testé avec Excel 2002 )


je te souhaite une bonne soiree
MichelXld

Message édité par: MichelXld, à: 10/05/2005 18:16
 

dg62

XLDnaute Barbatruc
Bonsoir thierry


Le problème a du déjà posé problème à bien du monde étant donné le nombre de fonctions ecrites pour réaliser un arrondi correcte.

Code:
Function Round2(X)
' Arrondi un nombre à 2 positions décimales
' Utilise l'arrondi arithmétique
  Round2 = Int(X * 100 + 0.5) / 100
End Function

Function Round2C(X)
' Arrondi une valeur monétaire à 2 positions décimales
' Utilise l'arrondi arithmétique
  If IsNull(X) Then
    Round2C = Null
  Else
    Round2C = CCur(Int(X * 100 + 0.5) / 100)
  End If
End Function

Function Round2CB(X As Variant) As Variant
' Arrondi bancaire d'une valeur monétaire à 2 décimales.
Dim Temp As Currency, ITemp As Currency, Digit As Integer
  If IsNull(X) Then Exit Function
  Round2CB = CCur(X / 100) * 100
End Function

Function RoundN(X, N As Integer)
' Arrondi un nombre à N positions décimales
' Utilise l'arrondi arithmétique
' N doit être dans la fourchette de 0-10 pour l'obtention de résultats corrects.
Dim Facteur As Long
  Facteur = 10 ^ N
  RoundN = Int(X * Facteur + 0.5) / Facteur
End Function

Function ArrondiG(Nombre As Double, Fraction As Integer, Direction As Integer)
'Objectif: Fonction générale d'arrondi jusqu'à 9'999'999'999'999.999
'Nombre: valeur à arrondir
'Fraction: Dénominateur de la fraction utilisée pour arrondir, par exemple 100 pour arrondir à 2 décimales,
' 4 pour arrondir au 1/4, 1000 pour arrondir à 3 décimales, etc.
'Direction: 1 = arrondi au plus proche, 2 arrondi au suivant, 3 arrondi au précédent
Dim NumFrac As Double, AFrac As Double, AFrac2 As Double, NouvArrond As Double
NumFrac = Nombre - Int(Nombre)
AFrac = 1 / Fraction
NumFrac = NumFrac / AFrac
NumFrac = Int(NumFrac + 0.5)
AFrac2 = AFrac * NumFrac
NouvArrond = Int(Nombre) + AFrac2
Select Case Direction
   Case 1 'arrondi arithmétique au plus proche
      ArrondiG = NouvArrond
   Case 2 'arrondi arithmétique au suivant (plus haut)
      If NouvArrond >= Nombre Then
         ArrondiG = NouvArrond
      Else
         ArrondiG = NouvArrond + AFrac
      End If
   Case 3 'arrondi arithmétique au prédédent (plus bas)
      If NouvArrond < Nombre Then
         ArrondiG = NouvArrond
      Else
         ArrondiG = NouvArrond - AFrac
      End If
   End Select
End Function

Public Function ArrondiGlobal(ByVal Nombre As Variant, NbreDec As Long) As Double
'Objectif:  Fonction générale d'arrondi au plus proche, jusqu'à 9'999'999'999'999.999
'Arguments: Nombre = valeur à arrondir, NbreDec = nombre de décimales désirées pour le résultat

Dim dblFraction As Double, varTemp As Variant, intSgn As Integer
If Not IsNumeric(Nombre) Then
'génère une erreur indiquant que l'on a fourni un paramètre incorrect
    Err.Raise 5
End If
'Calcul de la fraction utilisée pour arrondir au nombre voulu de décimales
dblFraction = 10 ^ NbreDec
'Est-ce un nombre négatif ou positif ?
'intSgn contiendra -1, 0, ou 1
intSgn = Sgn(Nombre)
Nombre = Abs(Nombre)
'Effectue le calcul principal
varTemp = CDec(Nombre) * dblFraction + 0.5
'Termine le calcul de l'arrondi
ArrondiGlobal = intSgn * Int(varTemp) / dblFraction
End Function

Bonne soirée
 

MichelXld

XLDnaute Barbatruc
rebonsoir @+Thierry , bonsoir Didier

mon anglais n'est pas terrible mais il semblerait que ce lien traite du meme sujet

http://support.microsoft.com/default.aspx?scid=kb;en-us;225330

les 2 fonctions ne renvoient donc pas toujours la meme valeur

Sub Test()
MsgBox Round(10.5, 0)
MsgBox Application.WorksheetFunction.Round(10.5, 0)
End Sub

pourtant dans ton classeur tous les criteres ne semblent pas totalement remplis pour que le probleme survienne :
You set the numdecimalplaces argument to zero, or omit this argument.
and
The expression contains an even numbered integer ending in the decimal .5.


la solution proposée dans l'aide :
If you want to use a round function consistent with Excel's worksheet function, use the WorksheetFunction property


bonne soiree
MichelXld
 

Hellboy

XLDnaute Accro
Bonjour a tous

Je te renvois ton fichier et dis moi ce que vous en pensez.

[file name=VBA-Round-Wrong-Calculation_20050510215234.zip size=8637]http://www.excel-downloads.com/components/com_simpleboard/uploaded/files/VBA-Round-Wrong-Calculation_20050510215234.zip[/file]
 

Pièces jointes

  • VBA-Round-Wrong-Calculation_20050510215234.zip
    8.4 KB · Affichages: 54

_Thierry

XLDnaute Barbatruc
Repose en paix
Bonsoir Michel, Didier, Philippe

Tout d'abord grand merci à tous d'avoir pris un peu de votre temps pour me répondre et en plus pour Michel d'avoir même fait des recherches.

Tout ce que vous avez testé démontre quand même bien une faille dans la programmation VBA :

MyResult = Round(MySum / MyCalculation * etc, 2)

Contrairement à :

Application.WorksheetFunction.Round(MySum / MyCalculation * etc, 2)

La démonstration de Michel est claire là dessus !

Ce qui m'interpelle le plus c'est qu'il faille que je m'en rende compte dans une application développée et surtout déployée professionnellement et dénoncée par un concours de circonstance pour que j'arrive à venir poster cette question avec vous mes amis d'XLD... (no comment, car c'est moi qui passe pour un c... vis à vis de mes collègues de travail !)

Enfin, dons après une journée assez longue je ne vais pas plancher là dessus dès maintenant, mais ce que je peux vous dire dès maintenant c'est Merci !! Thank You !!!

But I'll be back !!! Asta la vista baby !

Bonne Nuit (ou plutôt bonne journée !!!)
@+Thierry
 

Discussions similaires

Réponses
5
Affichages
112

Statistiques des forums

Discussions
312 182
Messages
2 086 001
Membres
103 084
dernier inscrit
Hervé30120