Put this in a code module:
Function Factors(ByVal dNum As Double, Optional bRevOrder As Boolean = False) As Variant
' shg 2006-0923
' 2006-0604 - added bRevOrder argument
' Returns a comma-delimited string of the factors of dNum
Dim vFac As Variant
vFac = IsPrime(dNum, True)
Select Case VarType(vFac)
Case vbError, vbString
Factors = vFac
Case Else
Do Until VarType(vFac) = vbBoolean
If bRevOrder Then
Factors = "," & CStr(vFac) & Factors
Else
Factors = Factors & CStr(vFac) & ","
End If
dNum = dNum / vFac
vFac = IsPrime(dNum, True)
Loop
If bRevOrder Then
Factors = CStr(dNum) & Factors
Else
Factors = Factors & CStr(dNum)
End If
End Select
End Function
Function IsPrime(dNum As Double, Optional bFirstFactor As Boolean = False) As Variant
' shg 2006-0923
' 2009-0603 fixed bug so if dNum Mod 15 = 0, returns 3 as a factor, not 5
' Returns: if dNum is:
' #VALUE! < 2
' "Too big!" > 1E+15
' #VALUE! <> Int(dNum)
' FALSE composite and bFirstFactor is False or omitted
' 1st factor composite and bFirstFactor is True
' TRUE prime and <= 1E+15
Dim dQuo As Double
Dim dFac As Double
If dNum < 2# Or Int(dNum) <> dNum Then
IsPrime = CVErr(xlErrValue)
ElseIf dNum = 2# Or dNum = 5# Then
IsPrime = True
ElseIf dNum > 1E+15 Then
IsPrime = "Too big!"
Else
' can't use Mod with numbers bigger than Longs, so ...
Select Case Right(CStr(dNum), 1)
Case "0", "2", "4", "6", "8"
IsPrime = IIf(bFirstFactor, 2#, False)
Case "5"
If bFirstFactor Then
dQuo = dNum / 3#
IsPrime = IIf(Int(dQuo) = dQuo, 3#, 5#)
Else
IsPrime = False
End If
Case Else
For dFac = 3# To Int(Sqr(dNum)) Step 2#
dQuo = dNum / dFac
If Int(dQuo) = dQuo Then
IsPrime = IIf(bFirstFactor, dFac, False)
Exit Function '------------------------------------->
End If
Next dFac
IsPrime = True
End Select
End If
End Function
If A1 contains 123331060025819, then =Factors(A1) returns 113,12517,87195439
Bookmarks