|
1个自定义开方主函数,外加3个辅助自定义函数:
开方过程,完全模拟手工开方的逐位计算。
但为了计算方便,算式扩大5倍,这样就可以把乘20变为20*5=100,简化计算了。
开方过程:
1、 开方余数a,开方结果b初始化。
2、 余数a=N-b^2,,每次增加1个数位更新为a=(N-b^2)*100
3、 设 b的下一位是t,即b=b*10+t
(b*10+t)^2=b^2*100+20*b*t+t*t=b^2*100+(20*b+t)*t
所以余数a=(N-b^2)*100-b^2*100-(20*b+t)*t=N-(20*b+t)*t
4. 每次增加位数需要减去(20*b*t+t*t)
扩大5倍a=N*5-(20*b*5+t*5)*t=N*5-(b*100+t*5)*t 所以这样扩大5倍就可以简化b的计算,而不影响数据结果的正确性。
- Function LongSqr(n&, Optional d& = 100) '对于任意正整数n、 返回其小数长度为d的平方根
- Dim a$, b$, j&, j1&, j2&, m&, p, t&, t1$, t2$
-
- p = Int(Sqr(n)) '利用自带函数开方取开方值整数部分
- m = d + Len(p) + 2 '整数+小数的总位数<m
-
- a = 5 * (n - p * p) '第一次计算直接扣除开方整数部分 然后扩大5倍好算
- b = p & 0 'b*10增加1位
- j1 = Len(a): j2 = Len(b)
-
- Do While j2 < m '循环直至小数位足够
- If j1 > j2 Or (j1 = j2 And a > b) Then 'a>b
-
- If j2 > 18 Then j = 18 Else j = j2 '取有效位数计算
- t = -Int(1 - Left(a, j + j1 - j2) / Left(b, j)) '取当前有效个位商t
-
- For t = t To 2 Step -1 '倒序检查合适的商数t (保证a-(b+t)*t>0)
- t1 = LargeSum(b, t * 5) '(b+t*5)
- t2 = LargeMult(t1, t) '(b+t*5)*t
- j = Len(t2)
- If j1 > j Or (j1 = j And a > t2) Then Exit For '足够大时退出
- Next
- If t = 1 Then t2 = LargeSum(b, 5) 't=1时简化计算
- a = LargeMinus(a, t2) 'a=a-b
- b = LargeSum(b, t & "0") 'b+t
- j1 = Len(a)
- Else 'a<b
- a = a & "00" 'a*100
- b = b & "0" 'b*10 相应增加1位
- j1 = j1 + 2: j2 = j2 + 1
- End If
- Loop
-
- LongSqr = p & "." & Mid(b, Len(p) + 1, d) '按指定小数位输出结果
- End Function
- Function LargeSum$(ByVal a$, ByVal b$) '大数a+小数b
- Dim i&, t$, t1$, t2$
- If Len(a) <= Len(b) Then
- LargeSum = Val(a) + Val(b)
- Else
- t1 = Left(a, Len(a) - Len(b)) '截取a前面超出b的部分不用计算
- t2 = Val(Right(a, Len(b))) + Val(b) '仅计算尾部对齐b的部分
- If Len(t2) > Len(b) Then '如果有进位
- t = Left(t2, 1) '截取进位数字t
- For i = Len(t1) To 1 Step -1 '倒序检查拼接
- If Mid(t1, i, 1) + t > 9 Then '超9时需进位
- Mid(t1, i, 1) = 0: t = 1 '本位归零、进位=1
- Else '不超9时直接相加然后退出
- Mid(t1, i, 1) = Mid(t1, i, 1) + t: Exit For
- End If
- Next
- If i = 0 Then t1 = 1 & t1 '检查至头部仍需进位时前面+1
- End If
- LargeSum = t1 & t2
- End If
- End Function
- Function LargeMinus$(ByVal a$, ByVal b$) '大数a-大数b
- Dim i&, n0&, n1&, r$, s$, t, t0
-
- n1 = Len(a): n0 = Len(b)
- If n1 < 29 Then LargeMinus = CDec(a) - CDec(b): Exit Function
- r = String(28, "0"): t0 = CDec(1 & r)
- For i = 1 To (n0 - 1) \ 28
- t = t0 + t + CDec(Mid(a, n1 - i * 28 + 1, 28)) - CDec(Mid(b, n0 - i * 28 + 1, 28))
- s = Right(r & t, 28) & s: If Len(t) > 28 Then t = 0 Else t = -1
- Next
- t = t - CDec(Left(b, n0 - i * 28 + 28))
- For i = i To (n1 - 1) \ 28
- t = t0 + t + CDec(Mid(a, n1 - i * 28 + 1, 28))
- If Len(t) > 28 Then
- LargeMinus = Left(a, n1 - i * 28) & Right(t, 28) & s: Exit Function
- Else
- s = Right(r & t, 28) & s: t = -1
- End If
- Next
- s = (CDec(Left(a, n1 - i * 28 + 28)) + t) & s
- For i = 1 To Len(s) - 1
- If Mid(s, i, 1) > 0 Then Exit For
- Next
- LargeMinus = Mid(s, i)
- End Function
- Function LargeMult$(ByVal a$, ByVal b&) '计算任意多位数的a 乘以单个数字b
- Dim i&, m&, n&, s$, s0$, t$
- s0 = String(27, "0")
- n = Len(a): m = Int((n - 1) / 27)
- For i = 1 To m
- t = Right(s0 & CDec(Mid(a, n - 27 * i + 1, 27)) * b + Val(t), 28)
- s = Right(t, 27) & s
- t = Left(t, 1)
- Next
- LargeMult = CDec(Left(a, n - 27 * m)) * b + Val(t) & s
- End Function
复制代码 |
|