Thread: Mod Function
View Single Post
  #8   Report Post  
Posted to microsoft.public.excel.worksheet.functions
Dana DeLouis Dana DeLouis is offline
external usenet poster
 
Posts: 947
Default Mod Function

This works good for numbers that are easly decomposed in 10th powers, but
what about strange numbers like mod(13523456273456;97). It's difficult ...


Hi. A 14 digit number can be done more directly via your code you listed
earlier.

Function MyMod(x, y)
MyMod = x - Int(x / y) * y
End Function

Hence
=MyMod(13523456273456,97) - 8

I am not exactly sure what the second code (MulMod32) is for.
In your main code, you are using Excel's MOD function. For some unknown
reason, Microsoft refuses to fix this bug, despite being asked for years.
You may want to use your own MOD function from above instead.

(I'm still stuck on this part
BX2N = MulMod32(BX2N, BX2N, N)


It "appears" to me to be an error, but it does work. (If done this way, I
was expecting MulMod32(BX2N, 2, N) )
I'll have to study it some more. However, it gave me a great idea on my own
code. Thanks.

Anyway, Large numbers can be broken down into smaller steps. Here's an
example of a 37 digit number.
The idea here is that you Mod a smaller group of the numbers. You append
the results to the beginning of the next group of numbers.


Sub TestIt()
Dim n As String
Dim x As Long
n = "1234567890123456789012345678901234567"
x = sMod(n, 97)
Debug.Print x
'// Your example
x = sMod("13523456273456", 97)
Debug.Print x
End Sub

Function sMod(n As String, x As Double) As Double
'// Mod(N, x) where N is a Long string
Dim s As String
Dim z As String
Dim P As Long
Const Stp As Long = 7
z = vbNullString
For P = 1 To Len(n) Step Stp
s = z & Mid$(n, P, Stp)
z = CStr(CDbl(s) Mod x)
Next P
sMod = CDbl(z)
End Function


On your question of
Suppose you have this number for a bank check:
00020001 01234567890 12345678CD 12


I am not familiar with this, but the placement of the check digit appears to
be incorrect.
I was expecting it to be the last two digits.

There are lots of internet recourses, but here's one...
http://www.pangaliit.ee/files/eng_Co...ementation.pdf

Does your data follow the pattern listed there?

For your Mod question, Steps 1.1 - 1.3 near the botton are following the
code above.
Step 1.2 is a little confusing.

What they are doing is taking 67 from step 1.1 and appending it to "6789012"
So, what they are actually doing in step 1.2 is Mod(676789012,97) -30

Anyway, hope this is of some help. Good luck.

--
HTH :)
Dana DeLouis
Windows XP & Excel 2007


"Diogo" wrote in message
...
Dana, thanks you putted me in the right direction, found this code on the
net.

Function PowerMod(ByVal B As Long, ByVal X As Long, ByVal N As Long) As
Long
'================================================= =============
'
' Dr Memory's "PowerMOD" function (Nov 2003)
'
' Returns B ^ X mod N
'
' 100% VB, no API, no DLL, and no Overflow
'
' Superfast, only 1 iteration for each BIT in X
' (i.e. max 31 iterations!).
'
' Valid for all 0 < N,X,B < &H7FFFFFFF = 2 ^ 32 - 1
' < 2,147,483,647
'
' Method:
' Binary Decomposition/Residual of the Exponent
'
'================================================= ==============
Dim K As Long
Dim BX2N As Long
K = 1
BX2N = B ' B^1

Do While X 0
If X Mod 2 Then K = MulMod32(BX2N, K, N) ' K = (BX2N * K) mod N
BX2N = MulMod32(BX2N, BX2N, N) ' BX2N = (BX2N ^ 2) mod N
X = X \ 2
Loop
PowerMod = K ' that's all, folks!
End Function

Function MulMod32(ByVal A As Long, ByVal B As Long, ByVal M As Long)
'
' return A * B mod M without risking overflow
'
Const MAXLONG = &H7FFFFFFF
Dim MM As Long
A = A Mod M
While B 0
If (B Mod 2) = 1 Then
If A MAXLONG - MM Then ' (A + MM) Mod M will overflow
If A <= MM Then MM = A - (M - MM) Else MM = MM - (M - A)
Else
MM = (A + MM) Mod M ' it's safe
End If
End If

If A MAXLONG - A Then ' ditto for 2*A mod M
A = A - (M - A)
Else
A = (A + A) Mod M
End If
B = B \ 2
Wend
MulMod32 = MM
End Function

This works good for numbers that are easly decomposed in 10th powers, but
what about strange numbers like mod(13523456273456;97). It's difficult to
decompose it without loosing significant decimal places along the way. Any
thoughts?
Thanks.