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.
CodePudding user response:
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
CodePudding user response:
Get Remainder From Large Integer
Sub GetLargeRemainderTEST()
Const LargeInteger As String = "3545123008254150481059068660418190917230"
Const Divisor As Long = 97
Debug.Print GetLargeRemainder(LargeInteger, Divisor) ' 37
End Sub
Function GetLargeRemainder( _
ByVal LargeInteger As String, _
ByVal Divisor As Long) _
As Long
Dim Dividend As String
Dim Remainder As Long
Do While Len(LargeInteger) > 0
Dividend = IIf(Remainder = 0, "", CStr(Remainder)) _
& Mid(LargeInteger, 1, 1)
Remainder = CLng(Dividend) Mod Divisor
'Debug.Print Dividend, Remainder, LargeInteger
LargeInteger = Mid(LargeInteger, 2, Len(LargeInteger) - 1)
Loop
GetLargeRemainder = Remainder
End Function
Debug.Print
Result
3 3 3545123008254150481059068660418190917230
35 35 545123008254150481059068660418190917230
354 63 45123008254150481059068660418190917230
635 53 5123008254150481059068660418190917230
531 46 123008254150481059068660418190917230
462 74 23008254150481059068660418190917230
743 64 3008254150481059068660418190917230
640 58 008254150481059068660418190917230
580 95 08254150481059068660418190917230
958 85 8254150481059068660418190917230
852 76 254150481059068660418190917230
765 86 54150481059068660418190917230
864 88 4150481059068660418190917230
881 8 150481059068660418190917230
85 85 50481059068660418190917230
850 74 0481059068660418190917230
744 65 481059068660418190917230
658 76 81059068660418190917230
761 82 1059068660418190917230
820 44 059068660418190917230
445 57 59068660418190917230
579 94 9068660418190917230
940 67 068660418190917230
676 94 68660418190917230
948 75 8660418190917230
756 77 660418190917230
776 0 60418190917230
0 0 0418190917230
4 4 418190917230
41 41 18190917230
418 30 8190917230
301 10 190917230
109 12 90917230
120 23 0917230
239 45 917230
451 63 17230
637 55 7230
552 67 230
673 91 30
910 37 0
37