下面给出大数的加减乘除函数,支持正负数:
程序代码:
Option Explicit
Function Rept0(n) ' n 个 0 的字符串
Dim s, i
s = ""
For i=1 To n
s = s & "0"
Next
Rept0 = s
End Function
Sub BigNumAdjLen(x, y) ' 调整大数字x、y(均正数)长度一致,短数左边+0
Dim lenx, leny
lenx = Len(x)
leny = Len(y)
If lenx>leny Then y = Rept0(lenx-leny) & y
If lenx<leny Then x = Rept0(leny-lenx) & x
End Sub
Sub BigNumLTrim0(x) ' 删除大数左边多余的0(无负数)
Dim i, lenx
lenx = Len(x)
For i=1 To lenx-1
If mid(x,i,1)<>"0" Then Exit For
Next
If i>1 Then x = Mid(x, i, Len(x)-i+1)
End Sub
Sub BigNumFlag(x, flagx, absx) ' 获取长数字的正负号和绝对值
If Left(x,1)="-" Then
flagx = "-"
absx = Right(x,Len(x)-1)
Else
flagx = "+"
absx = x
End If
End Sub
Function BigNumCmp(x, y) '大数比较,x>0、x=y、x<y 分别返回 1、0、-1
Dim flagx, flagy, absx, absy, z
If x=y Then
z = 0
Else
BigNumFlag Trim(x), flagx, absx
BigNumFlag Trim(y), flagy, absy
BigNumAdjLen absx, absy
Select Case flagx & flagy
Case "++": If absx>absy Then z=1 Else z=-1
Case "--": If absx>absy Then z=-1 Else z=1
Case "+-": z = 1
Case "-+": z = -1
End Select
End If
BigNumCmp = z
End Function
Function BigNumAdd(x, y) '加法,判断正负数后调用纯加或者减
Dim flagx, flagy, absx, absy, z
BigNumFlag Trim(x), flagx, absx
BigNumFlag Trim(y), flagy, absy
Select Case flagx & flagy
Case "++": z = BigNumAdd2(absx, absy)
Case "--": z = "-" & BigNumAdd2(absx, absy)
Case "+-": z = BigNumSub(absx, absy)
Case "-+": z = BigNumSub(absy, absx)
End Select
BigNumAdd = z
'WScript.Echo "DEBUG BigNumAdd(" & x & "," & y & ") = " & z
End Function
Function BigNumAdd2(x, y) '纯加(无负数)
Dim z, i, t, zi
BigNumAdjLen x, y
z = ""
t = 0 ' 进位
For i = Len(x) To 1 Step -1
zi = Asc(mid(x, i, 1)) + Asc(mid(y, i, 1)) - 96 + t
If zi>=10 Then
t = 1
zi = zi - 10
Else
t = 0
End If
z = zi & z
Next
If t>0 Then z = t & z
BigNumAdd2 = z
'WScript.Echo "DEBUG BigNumAdd2(" & x & "," & y & ") = " & z
End Function
Function BigNumSub(x, y) '减法,判断正负数后调用纯加或者纯减
Dim flagx, flagy, absx, absy, absxlen, absylen, z
BigNumFlag Trim(x), flagx, absx
BigNumFlag Trim(y), flagy, absy
Select Case flagx & flagy
Case "++": If BigNumCmp(absx,absy)>=0 Then z = BigNumSub2(absx, absy) Else z = "-" & BigNumSub2(absy, absx)
Case "--": If BigNumCmp(absx,absy)>0 Then z = "-" & BigNumSub2(absx, absy) Else z = BigNumSub2(absy, absx)
Case "+-": z = BigNumAdd2(absx, absy)
Case "-+": z = "-" & BigNumAdd2(absx, absy)
End Select
BigNumSub = z
'WScript.Echo "DEBUG BigNumSub(" & x & "," & y & ") = " & z
End Function
Function BigNumSub2(x, y) '纯减(无负数,x>=y)
Dim z, i, t, zi
BigNumAdjLen x, y
z = ""
t = 0 ' 借位
For i = Len(x) To 1 Step -1
zi = (Asc(mid(x, i, 1)) - 48) - (Asc(mid(y, i, 1)) - 48) - t
If zi>=0 Then
t = 0
z = zi & z
Else
t = 1
z = (zi + 10) & z
End If
Next
BigNumLTrim0 z
BigNumSub2 = z
'WScript.Echo "DEBUG BigNumSub2(" & x & "," & y & ") = " & z
End Function
Function BigNumMul(x, y) '乘法,判断正负数后调用纯乘
Dim flagx, flagy, absx, absy, absxlen, absylen, z
BigNumFlag Trim(x), flagx, absx
BigNumFlag Trim(y), flagy, absy
Select Case flagx & flagy
Case "++","--": z = BigNumMul2(absx, absy)
Case "+-","-+": z = "-" & BigNumMul2(absx, absy)
End Select
BigNumMul = z
'WScript.Echo "DEBUG BigNumMul(" & x & "," & y & ") = " & z
End Function
Function BigNumMul2(x, y) '纯乘法(无负数)
Dim z, i, yi
z = "0"
If x<>"0" And y<>"0" Then
For i=1 To Len(y)
yi = (Asc(mid(y, i, 1)) - 48)
z = BigNumAdd2(BigNumMul3(z, 10), BigNumMul3(x, yi))
Next
End If
BigNumMul2 = z
'WScript.Echo "DEBUG BigNumMul2(" & x & "," & y & ") = " & z
End Function
Function BigNumMul3(x, n) '纯乘法(无负数)2, 乘数n为一位数(0-10)
Dim z, i, t, zi, m
Select Case n
Case 0: z = "0"
Case 10: z = x & "0"
Case Else:
z = ""
t = 0 ' 进位
For i=Len(x) To 1 Step -1
zi = (Asc(mid(x, i, 1)) - 48) * n + t
m = zi Mod 10
t = (zi - m) / 10
z = m & z
Next
If t>0 Then z = t & z
End Select
BigNumMul3 = z
'WScript.Echo "DEBUG BigNumMul3(" & x & "," & n & ") = " & z
End Function
Function BigNumDiv(x, y) '除法,判断正负数后调用纯除
Dim flagx, flagy, absx, absy, absxlen, absylen, z
BigNumFlag Trim(x), flagx, absx
BigNumFlag Trim(y), flagy, absy
Select Case flagx & flagy
Case "++","--": z = BigNumDiv2(absx, absy)
Case "+-","-+": z = "-" & BigNumDiv2(absx, absy)
End Select
BigNumDiv = z
WScript.Echo "DEBUG BigNumDiv(" & x & "," & y & ") = " & z
End Function
Function BigNumDiv2(x, y) '纯除(无负数)
Dim i, z, xi, zi, m
'WScript.Echo "DEBUG BigNumDiv2(" & x & "," & y & ") Start"
xi = "0" '第i次被除数
m = "0" '上次整除的余数
z = ""
For i=1 To Len(x)
xi = BigNumAdd(BigNumMul(m, 10), mid(x,i,1))
'WScript.Echo "DEBUG BigNumDiv2(" & x & "," & y & ") i=" & i & ", xi=" & xi
BigNumDiv3 xi, y, zi, m
z = z & zi
Next
BigNumLTrim0 z
BigNumDiv2 = z
'WScript.Echo "DEBUG BigNumDiv2(" & x & "," & y & ") = " & z
End Function
Sub BigNumDiv3(x, y, z, m) '纯除(无负数,商为一位数),x 整除 y,商 z、余 m
Dim i, yi
If y="1" Then
z = x
m = "0"
ElseIf x="0" Then
z = "0"
m = "0"
ElseIf x=y Then
z = "1"
m = "0"
ElseIf BigNumCmp(x, y)<0 Then 'x<y
z = "0"
m = x
Else'x>y
z = 1
m = BigNumSub(x, y)
While BigNumCmp(m, y)>=0
z = z + 1
m = BigNumSub(m, y)
WEnd
End If
'WScript.Echo "DEBUG BigNumDiv3(" & x & "," & y & ") = " & z & " ... " & m
End Sub
WScript.Echo "DEBUG:" & BigNumDiv("123", "1")
WScript.Echo "DEBUG:" & BigNumDiv("123456789", "1")
WScript.Echo "DEBUG:" & BigNumDiv("1234567890", "10")
WScript.Echo "DEBUG:" & BigNumDiv("15185185047", "123456789")
WScript.Echo "DEBUG:" & BigNumDiv("15185185047", "123")
WScript.Echo "DEBUG:" & BigNumDiv("56088", "456")
MsgBox BigNumDiv("12193263113702179556720073558516635681494230864252625391052410", "987654321098765432109876543210")
'原帖给的答案 123456789012345678901234567890 是错误的,正确结果是 12345678901234567924651296698834
下图是测试数据的运行情况,原帖子给出的示例用PHP8.2.3进行了交叉验证
确实老了, 等我调试通过的时候,已经有高手发了完整代码,长江后浪推前浪,好。