Search code examples
excelvbamathbigint

VBA calculate with numbers in range 10^40


I asked a similar question yesterday, but for smaller numbers. So today again :-)

I am trying to calculate: A random number in the range 10^40 mod a random number in the range of 100. I saved the first random number as a Variant because the number is too big to be saved as an Integer.

The result of the solution should be something between 1 and 100, so it could be saved as an Integer.

For example calculation: 3545123008254150481059068660418190917230 mod 97 = 37. How to calc this by using VBA.

My idea is to break down the numbers into smaller numbers (prim factorization) and calculate the modulo on smaller numbers, so we don't need to calculate in the range of 10^40.

Here the solution with smaller numbers:

Sub test_this()
    Debug.Print find_modulus("300400000717120000131495", 97)
End Sub

Function find_modulus(large_number As String, divisor As Long)
    Dim quotient As Variant, integer_quotient As Variant
    quotient = CDec(large_number)
    integer_quotient = Int(quotient / divisor) * divisor
    find_modulus = quotient - integer_quotient
End Function

The Output in this example is 1 and it is correct.

But with this calculation I get errors...
For example calculation: 3545123008254150481059068660418190917230 mod 97 = 37. How to calc this by using VBA.


Solution

  • You can do the division in chunks, treating large numbers as a string and chopping them up into smaller pieces which can be processed in sequence.

    To start with your example: 3545123008254150481059068660418190917230 Mod 97. We can take the first 9 digits "354512300". The Mod of this is "95". We prepend that onto the string and then take 9 digits to form the next sequence, "958254150". Repeat that for the entire string and eventually your last section is "55230", whose modulus is 37!

    Function find_modulus(ByVal number As String, ByVal divisor As Long) As Long
        While Len(number) > 9
            number = (CLng(Left(number, 9)) Mod divisor) & CStr(Mid(number, 10))
        Wend
        find_modulus = CLng(number) Mod divisor
    End Function