第6节 高精度计算问题
模拟演练
1.大数加法。在文本框Text1和Text2中输入两个大数,点击“相加”按钮后,在文本框Text3中输出结果。
实现上述功能的VB程序如下,请在划线处填入合适的代码。
Private Sub Command1_Click()
Dim s1 As String
Dim s2 As String
Dim s3 As String
Dim l1 As Integer
Dim l2 As Integer
Dim l3 As Integer
Dim a(1 To 100) As Integer
Dim b(1 To 100) As Integer
Dim c(1 To 100) As Integer
Dim t As Integer
s1 = Text1.Text
s2 = Text2.Text
l1 = Len(s1)
l2 = Len(s2)
For i = l1 To 1 Step -1
a(i) = ① ?
Next
For i = l2 To 1 Step -1
b(i) =Val(Mid(s2, l2 - i + 1, 1))
Next
If l1 > l2 Then l3 = l1 Else l3 = l2
t = 0
For i = 1 To l3
c(i) = a(i) + b(i) + t
t = c(i) 10
c(i) = ② ?
Next
For i = 1 To l3
s3 = Str(c(i)) + s3
Next
If ③ Then s3 = “1” + s3?
Text3.Text = s3
End Sub
答案 ①Val(Mid(s1, l1 - i + 1, 1)) ②c(i) Mod 10 或c(i)- 10 ③t = 1
解析 ①从个位开始,按位取出s1中每一位数,存入数组a中。②变量t存储当前位相加后的进位,c(i)是当前位相加后的结果,因此进位后,c(i)= c(i) Mod 10。③最高位相加后产生了进位,则需要在结果前再加一个“1”。
2.当计算机程序中无法用普通数据类型表示位数较多的乘数和计算结果时,就需要采用高精度乘法。如,当两个各有20位数字的整数相乘时,就无法用长整型(Long)数据类型来表示。高精度乘法运算就是运用数组,用程序模拟列竖式计算的过程。两个正整数进行高精度乘法计算的一般算法如下:
(1)将第一个整数各位上的数字按照从低位到高位的顺序依次存入数组a(1)、a(2)、…、a(La)中,将另一个整数各位上的数字按照从低位到高位的顺序依次存入数组b(1)、b(2)、…、b(Lb)中。其中,La表示第一个整数的位数,Lb表示第二个整数的位数;
(2)按照从低位到高位的顺序,将两个整数各位数值进行逐位乘法计算(第一轮先让b(1)依次乘a(1)、a(2)…a(La),第二轮再让b(2)依次乘a(1)、a(2)、…、a(La),依次进行),每位的乘法结果也按照低位到高位的顺序依次存入数组ans(1)、ans(2)、ans(3)中;
(3)对数组ans中的计算结果进行从低位到高位的进位处理;
(4)统计数组ans中实际计算结果的有效数值位数,并将位数值存入变量length;
(5)按照高位到低位的顺序输出数组ans中的计算结果。
小明按照上述方法设计了一个两数进行高精度乘法计算的VB程序,功能如下:在文本框Text1和Text2中依次输入两个整数,单击“计算”按钮Command1,程序进行高精度乘法计算,并在标签Label4中输出计算结果。
/
实现上述功能的VB程序如下:
(1)请在划线处填入合适代码。
Dim a(1 To 30) As Integer, b(1 To 30) As Integer
Dim ans(1 To 60) As Integer
Dim La As Integer, Lb As Integer
Dim length As Integer
Private Sub Command1_Click()
Dim i As Integer, j As Integer, t As Integer, temp As String
’将两个乘数(正整数)各数位上的数字按照上述算法依次存入数组a和b,每个正整数位数分别保存到变量La和Lb;将保存结果的数组ans(i)值初始化为零(该部分程序代码略)
For i = 1 To Lb ’按低位到高位的顺序进行列竖式的逐位乘法
For j = 1 To La
ans(i + j - 1) = ① + b(i) * a(j) ?
Next j
Next i
For i = 1 To La + Lb ’对计算结果进行进位处理
ans(i+1) =ans(i +1)+ ans(i) 10
ans(i) = ② ?
Next i
length = La + Lb ’最多位数
Do While ans (length) = 0 ’计算实际位数
length = length - 1
Loop
For i = ③ To 1 Step -1?
Label4.Caption = Label4.Caption + Str(ans(i))
Next i
End Sub
(2)根据本题算法,若输入的两个整数分别为5125和18,则在输出乘法计算结果时,变量length的值为 。?
答案 (1)①ans(i+j-1) ②ans(i) Mod 10 ③length (2) 5
解析 (1)①对应位置上的数字分别相乘后再相加所得的和存入 ans 数组中。需要注意的是,a(i)乘b(j)的结果是贡献给ans(i+j-1)的,如a(1)乘b(4)、a(2)乘b(3)、a(3)乘b(2)、a(4)乘b(1)都是贡献给ans(4)的,因此这里需要累加。②ans(i)10是计算进位,进位完后,ans(i)=ans(i) Mod 10。③从最高位到最低位按位输出,变量length是已经去前置0以后的实际位数。
(2)5125*18=92250,所以实际位数是5位。
3.小明编写了一个求真分数精确值的VB程序。程序运行时,在文本框Text1中输入被除数,在文本框Text2 中输入除数,并保证被除数小于除数,单击“计算”按钮Command1,在标签Label3中显示结果(最多计算到第20位)。程序运行界面如图所示。
/
(1)实现上述功能的VB程序如下,请在划线处填入合适的代码。
Dim a(1 To 20) As Integer, b(1 To 20) As Integer
’判断循环节
Function Judge(position As Integer) As Boolean
Dim i As Integer
For i = 1 To position - 1
If b(i) = ① Then Judge = False : Exit Function?
Next i
Judge = True
End Function
Private Sub Command1_Click()
Dim m As Integer, n As Integer, x As Integer, i As Integer
Dim flag As Boolean, st As String
m = Val(Text1.Text):n = Val(Text2.Text)
st = Str(m) + “/” + Str(n) + “=”
st = st + “0.”
i = 1: x = 1: flag = True
b(1) = m
m = m * 10
Do While i <= 20 And flag = True
a(i)= ② ?
If a(i) > 0 Then
x = x + 1
b(x) = m Mod n
m = b(x) * 10
Else
m = m * 10
End If
flag = Judge(x)
If b(x) =0 And x <> 0 Then flag = False
st = ③ ?
Loop
Label3.Caption = st
End Sub
(2)运行程序,在文本框Text1中输入被除数1,在文本框Text2中输入除数3,单击“计算”按钮Command1,在标签Label3中显示的结果是 。?
答案 (1)① b(position) ② mn ③ st+Str(a(i)) (2) 1/3=0.3
解析 (1) ①自定义函数Judge用于判断循环节是否已经出现。两数相除,商存在数组a中,余数存在数组b中。当某次余数跟前面某次余数相同时,表示循环节出现了。此处用了顺序查找,将当前余数b(position)与前position-1次余数比较,如果相同,则循环节出现了,将Judge 设置为False。②数组a存放每次得到的商,每一次的商a(i)等于上一次的余数*10除以除数n,再取整。从题中可知,m=余数*10,然后给下一次用,因此此处填a(i)= mn。③st是最后的结果,是把所有的商按位串起来,a(1)是第一个商,因此st = st+Str(a(i))。
(2)1除以3得到0.3333…,无限循环,循环节是3,因此结果是0.3。
课件6张PPT。
第6节 高精度计算问题 在VB中,各种数据类型都有它的值范围(因为受到存储空间的限制),
比如Integer(2个字节),值范围是-32768~32767,即-216~216-1;Long(4个字节)的范围是-232~232-1;Single(4个字节)的有效数字约6~7位;Double(8个字节)的有效数字约14~15位。
因此,当超过一定位数的大数据进行数学运算时,普通变量可能无法存储运算数或结果值,有一种解决方案是采用数组来存储。教材研读 1.加法
解决方案:将相加的两个数,按位存入两个数组中,从两个数组的最低
位(即个位)开始,将每一位的和存入第三个数组中。同时,在相加的过程中,考虑进位问题。两数相加,要么没进位,比如3+4=7,要么进位是1,如9+9=18。 2.减法
解决方案:将相减的两个数,按位存入两个数组中,从两个数组的最低
位(即个位)开始,将每一位的差存入第三个数组中。同时,在相减的过程中,考虑借位问题,跟相加不一样的是,相减之前先判断大小,然后借位,最后相减。如果借位,一定借1。 3.乘法
情况一:多位数乘一位,将多位数按位存入数组中,然后从数组的最低
位(即个位)开始,依次与一位乘数相乘,并把结果存入另一个数组中。同时,在相乘的过程中,考虑进位问题。最小进位是1,如3×4=12;最大进位是8,如9×9=81。
情况二:多位数乘多位数。将两个乘数分别按位存入数组a和数组b中,然后将a数组的每一位(从个位开始)去乘b数组的最低位(即个位),结果存入数组c中,同时考虑进位问题;然后将a数组的每一位(从个位开始)去乘b数组的第二位(即十位),同时考虑进位问题,……,直至b数组的所有位
都乘完。因此这是一个双重循环,比较难的是进位问题。a(i)*b(j)和a(j)
*b(i)的结果都贡献给c(i+j-1),它们的进位都贡献给c(i+j)。 4.除法
情况一:大数除以大数,可以考虑用减法来实现。
情况二:整数形除以整数形,要求结果保留高精度。用一个数组来保留商的每一位,最后串在一起就是结果。由于商是用余数来求的,余数可以不保留,也可以保留。因此可以用另一个数组来保留每一次的余数,也可以用一个变量来存储最新的余数,用完再覆盖。数学常识一:整数除以整数,一定是有理数,即要么除尽,要么除不尽,除不尽的情况下结果必定是无限循环小数。如果是除不尽的情况,只要保留一个循环节即可。数学常识二:当某一次计算的余数(不是商)与之前某一次相等时,表示循环节出现。