【讨论】怎么才能使 a,b 两个整数相乘永远也不会溢出?

guoshaoning 2010-02-03 02:31:25
我的基本思路是将一个很大的整数拆成 一位一位的然后摹拟乘法基本运算那样,一位一位的乘,最后再把结果加起来。这个过程全是用string类型,所以不会出现溢出。

'窗体form1中代码
Option Explicit
Private Sub Command1_Click()
Dim strA As String
Dim strB As String
Dim arryC() As String

strA = Text1.Text
strB = Text2.Text

If strA = "" Or strB = "" Then
Exit Sub
End If

Dim cls As Class1
Set cls = New Class1

arryC() = cls.GetMultiply(strA, strB)

Text3.Text = Join(arryC())

End Sub

Private Sub Command2_Click()
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
End Sub

Private Sub Command3_Click()
Unload Me
End Sub

Private Sub Form_Load()
Text1.Text = "" '乘数a
Text2.Text = "" '乘数b
Text3.Text = "" '结果
Command1.Caption = "计算"
Command2.Caption = "清空"
Command3.Caption = "关闭"
End Sub

'类模块Class1中代码
Option Explicit
'把数字串儿分别放到数组中
Private Function GetArry(ByVal str As String) As Variant
Dim arry() As String
Dim i As Long
For i = 0 To Len(str) - 1
ReDim Preserve arry(i)
arry(i) = Left(Trim(str), 1)
str = Mid(Trim(str), 2, Len(str))
Next
GetArry = arry()
End Function
'将两个得到的数组按一个一个单位整数相乘得到结果
Public Function GetMultiply(ByVal strA As String, ByVal strB As String) As Variant
Dim arry() As String
Dim arryA() As String
Dim arryB() As String
Dim arryTemp() As String
Dim intA As Long
Dim intB As Long

Dim a, b, i, j As Integer
Dim tempC As Integer
Dim tempT As Long

arryA() = GetArry(strA)
arryB() = GetArry(strB)

ReDim arry((Len(strB) - 1), (Len(strA) + Len(strB) - 1)) As String

i = 0

For intB = UBound(arryB()) To 0 Step -1
b = CInt(arryB(intB))
tempT = 0
j = (Len(strA) + Len(strB) - 1)
For intA = UBound(arryA()) To 0 Step -1
a = CInt(arryA(intA))
tempC = (a * b) + tempT
arryTemp() = GetArry(CStr(tempC))

If UBound(arryTemp()) = 1 Then
arry(i, j - i) = arryTemp(1)
tempT = CInt(arryTemp(0))
Else
arry(i, j - i) = arryTemp(0)
tempT = 0
End If

If intA = 0 And tempT <> 0 Then
arry(i, j - 1 - i) = tempT
End If
j = j - 1
Next
If intB = 0 And tempT <> 0 Then
arry(i, 0) = tempT
End If
i = i + 1
Next

GetMultiply = GerSum(arry(), Len(strA) + Len(strB) - 1, Len(strB) - 1)
End Function
'按位求和得到结果
Private Function GerSum(ByRef arry() As String, ByVal IndeXx As Integer, ByVal IndeXy As Integer) As Variant
Dim i, j, k As Integer
Dim arryRt() As String
Dim arryTemp() As String
Dim temp, tempT As Long
k = 0
ReDim arryRt(IndeXx) As String
For i = IndeXx To 0 Step -1
temp = 0

For j = 0 To IndeXy
If arry(j, i) = "" Then
arry(j, i) = 0
End If
temp = temp + CLng(arry(j, i))
Next
temp = temp + tempT

arryTemp() = GetArry(CStr(temp))

If UBound(arryTemp()) = 1 Then
arryRt(i) = arryTemp(1)
tempT = CInt(arryTemp(0))
Else
arryRt(i) = arryTemp(0)
tempT = 0
End If
Next
GerSum = arryRt()
End Function
...全文
438 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2010-02-05
  • 打赏
  • 举报
回复
改用Ruby语言会更方便
  • 打赏
  • 举报
回复
永远就是……没有永远。哈哈
chinaboyzyq 2010-02-04
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 guoshaoning 的回复:]
我的写法其实只是理论上的,如果字符串无限长也不行!不知道用VB有没有别的办法?
[/Quote]

如果一个串变量放不下就用两个串来放,两个串变量放不下就用三。。。。。。

大概没有人知道永远有多远 :)
chinaboyzyq 2010-02-04
  • 打赏
  • 举报
回复
给你浇点凉水,永远是不可能滴,一个变长串的最大长度大约也就20亿个字符。

超大数乘法,VB的网上有不少。
给你个别人写的:

VB实现超大数的乘法运算2008-11-28 18:33'*************************************************************************
'**函 数 名:MPC
'**输 入:D1(String)=乘数 -
'** :D2(String)=被乘数 -
'**输 出:(String)乘积 -
'**功能描述:
'**全局变量:
'**调用模块:
'** 注 意:乘数、被乘数都只能由数字组成。
'**作 者:
'**日 期:2008-11-28 18:29:50
'**修 改 人:
'**日 期:
'**版 本:V1.0.0
'*************************************************************************
Public Function MPC(D1 As String, D2 As String) As String
Dim X, Y '两数长度
X = Len(D1): Y = Len(D2)
Dim A() As Integer
ReDim A(1 To X + Y, 1 To Y)
Dim I, J, C1, C2, CJ, JW
If Check1.Value = 1 Then
For C = 1 To X + Y
MPC = MPC & "-"
Next
MPC = MPC & vbCrLf
End If
For J = Y To 1 Step -1 'D2
JW = 0 '进位清0
C2 = Mid$(D2, J, 1) '每位数
For I = X To 1 Step -1 'D1
C1 = Mid$(D1, I, 1) '每位数
CJ = C1 * C2 + JW '计算乘积
C = I + J: R = Y + 1 - J
A(C, R) = CJ Mod 10 '本位
JW = CJ \ 10 '进位
Next
A(C - 1, R) = JW
If Check1.Value = 1 Then
Dim T, M
T = ""
For C = 1 To X + Y
MPC = MPC & A(C, R)
Next
MPC = MPC & vbCrLf
End If
Next
Dim B() As Integer
ReDim B(1 To X + Y)
JW = 0
For I = X + Y To 1 Step -1
Bit = JW
For J = 1 To Y
Bit = Bit + A(I, J)
Next
B(I) = Bit Mod 10
JW = Bit \ 10
Next
If Check1.Value = 1 Then
For C = 1 To X + Y
MPC = MPC & "-"
Next
MPC = MPC & vbCrLf
End If
If B(1) > 0 Then
MPC = MPC & B(1)
Else
MPC = MPC & Space(1)
End If
For I = 2 To X + Y
MPC = MPC & B(I)
Next
End Function

guoshaoning 2010-02-04
  • 打赏
  • 举报
回复
我的写法其实只是理论上的,如果字符串无限长也不行!不知道用VB有没有别的办法?
大家别光是围观啊!~
chinaboyzyq 2010-02-04
  • 打赏
  • 举报
回复
围观一下………………
fs822 2010-02-04
  • 打赏
  • 举报
回复
贴一段VB.net的运算符重载BigInt
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=403&lngWId=10
谁有兴趣改成VB的
fs822 2010-02-04
  • 打赏
  • 举报
回复
我知道C++上有BigInt类(自己写的啦)
VB上能不能也做个呢

应该可以,做完以后可以用得很爽啊
Dim a as bigInt
Dim b as bigInt
a=12345
b="12345678901234567890123456789012345678901234567890123456789012345678901234567890"
'记得当时int用完了就用字符串赋值
然后 a=a*b
就这样,运算符重载直接用。

java小鸟 2010-02-04
  • 打赏
  • 举报
回复
围观一下………………
guoshaoning 2010-02-04
  • 打赏
  • 举报
回复
楼上说的对,我的这个程序只是一种方法而已.
赵4老师 2010-02-04
  • 打赏
  • 举报
回复
永远有多远?
比宇宙的寿命还要长?

两个整数相乘最大会有多大?
比这个世界上所有电脑的内存和外存容量加起来都大?
FrankArmageddon 2010-02-03
  • 打赏
  • 举报
回复
不错啊,ACM有一道题目就是1234567890987654321!=?
舉杯邀明月 2010-02-03
  • 打赏
  • 举报
回复
围观一下………………
guoshaoning 2010-02-03
  • 打赏
  • 举报
回复
准备下班儿,走人!
guoshaoning 2010-02-03
  • 打赏
  • 举报
回复
9楼的比我的简单多啦!呵呵,不错!
guoshaoning 2010-02-03
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 magic7004 的回复:]
这个用VB做太麻烦了,而且效率太低。一定要做的话,用汇编吧。搂住搜一下多字节乘法的算法。
[/Quote]

汇编!!上学的时候似乎学过~毕业就还给老师了:<
magic7004 2010-02-03
  • 打赏
  • 举报
回复
这个用VB做太麻烦了,而且效率太低。一定要做的话,用汇编吧。搂住搜一下多字节乘法的算法。
Defanive 2010-02-03
  • 打赏
  • 举报
回复

这个是我写的,思路就是我们平时竖式的思路:

使用的时候直接调用Multiplay("123","123")

Private Function Multiply(ByVal Num1 As String, ByVal Num2 As String) As String
Dim Res As String
For i = Len(Num2) To 1 Step -1
Res = Multi(Num1, CInt(Mid(Num2, i, 1)))
Multiply = Plus(Multiply, Res & String(Len(Num2) - i, "0"))
Next
End Function

Private Function Multi(ByVal Num1 As String, ByVal Num2 As Integer) As String
Dim AddNext As Integer
Dim Res As String
For i = Len(Num1) To 1 Step -1
Res = Right(0 & CInt(Mid(Num1, i, 1) * Num2 + AddNext), 2)
Multi = Right(Res, 1) & Multi
AddNext = Left(Res, 1)
Next
If Not AddNext = "0" Then Multi = AddNext & Multi
End Function

Private Function Plus(ByVal Num1 As String, ByVal Num2 As String) As String
Dim AddNext As Integer
Dim Res As String
If Len(Num2) > Len(Num1) Then
tmp = Num1
Num1 = Num2
Num2 = tmp
End If
Num2 = Right(String(Len(Num1), "0") & Num2, Len(Num1))
For i = Len(Num1) To 1 Step -1
Res = Right(0 & CInt(Mid(Num1, i, 1)) + CInt(Mid(Num2, i, 1)) + AddNext, 2)
Plus = Right(Res, 1) & Plus
AddNext = Left(Res, 1)
Next
If Not AddNext = "0" Then Plus = AddNext & Plus
End Function
qq9649869 2010-02-03
  • 打赏
  • 举报
回复
怎么验证呢?
guoshaoning 2010-02-03
  • 打赏
  • 举报
回复
有些结果太大了,我没办法验证他的正确性,这个思路应该没问题吧?
加载更多回复(6)

7,762

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧