Consider these two routines in excel vba:
Code:
Public Function VBRoundError(numberOfLoops As Long, Optional Round As Boolean) As Double
Dim i As Long
Dim sum As Double
For i = 0 To numberOfLoops
If Round Then
sum = RoundIt(sum + 0.01, 7)
Else
sum = sum + 0.01
End If
Next
VBRoundError = sum
End Function
Public Function RoundIt(ByVal aNumberToRound As Double, Optional ByVal aDecimalPlaces As Double = 0) As Double
Dim nFactor As Double
Dim nTemp As Double
nFactor = 10 ^ aDecimalPlaces
nTemp = (aNumberToRound * nFactor) + 0.5
RoundIt = Int(CDec(nTemp)) / nFactor
End Function
Once you place these routines into a module you can access the VBRoundError function by typing this "=VBRoundError(99)" into a cell.
If I type these into cells within excel:
Code:
=VBRoundError(99) excel displays 1.000000000000000000
=VBRoundError(999) excel displays 9.999999999999830000
=VBRoundError(9999) excel displays 100.000000000014000000
You can clearly see that there is rounding error taking place. This is just the way that VB/A behaves.
If I use this:
Code:
=VBRoundError(99,true) excel displays 1.000000000000000000
=VBRoundError(999,true) excel displays 10.000000000000000000
=VBRoundError(9999,true) excel displays 100.000000000000000000
I get nice even values. There really is no way around this because of the way VB/A works.
When working with double or single precision numbers, you should always test using a tolerance or delta value instead of directly comparing two doubles. I would use something like:
Code:
if (a-b) < 0.00001 then
If you are concerned with readability (as you should be) you can create a function that returns a boolean:
Code:
public function ToleranceTest(num1 as double, num2 as double, tolerance as double) as boolean
if (num1 - num2) < tolerance then
ToleranceTest = true
else
ToleranceTest = false
endif
end function