I am trying to obtain the fractional part of a number in VBA in Excel. Is there a particular method that works best to get the fractional part of a number?
I have tried two different methods. One of these methods gives the expected result of 0.1. The other method gives an unexpected result of 9.99999999999996E-02. Please help me understand why I am receiving this unexpected result. Please refer to the following code:
Dim DecNumber As Double
Dim TempSplit() As String
Dim DecFract As Double
DecNumber = 15.1
'METHOD 1
'Gives unexpected result of 9.99999999999996E-02
DecFract = DecNumber - Int(DecNumber)
'METHOD 2
'Gives expected result of 0.1
TempSplit() = Split(DecNumber, ".")
DecFract = TempSplit(1) / (10 ^ Len(CStr(TempSplit(1))))
The differences are due to the fact that calculations in Excel are based on the binary system, and the accuracy of calculations with double precision is limited to about 15 significant digits. When subtracting similar numbers, the relative accuracy decreases and inexact digits may appear in the last places of the expansion. But in general, the first method provides better accuracy if the example is not specially chosen.
You can try to reduce the occurrence of random trailing digits by using rounding, but this is also not 100% effective.
Compare results for different numbers. You can also use Currency
type as proposed by @taller if 4 decimal places accuracy is enough for you.
Sub Decimals()
Dim DecNumber As Double
Dim TempSplit() As String
Dim DecFract As Double
Dim fact As Double
' DecNumber = 15.1
DecNumber = 145.1 / 7
' DecNumber = 15.0625
'METHOD 1
'Gives unexpected result of 9.99999999999996E-02
DecFract = DecNumber - Int(DecNumber)
Debug.Print DecFract
'METHOD 1A
fact = 1E+17
DecFract = (Round(DecNumber * fact) - Int(DecNumber) * fact) / fact
Debug.Print DecFract
'METHOD 2
'Gives expected result of 0.1
TempSplit() = Split(DecNumber, ".")
DecFract = TempSplit(1) / 10 ^ Len(TempSplit(1))
Debug.Print DecFract
'METHOD 2A
' TempSplit() = Split(DecNumber, ".")
fact = 10 ^ Len(TempSplit(1))
DecFract = (Round(DecNumber * fact) - Int(DecNumber) * fact) / fact
Debug.Print DecFract
End Sub