Excel 和 Excel VBA 没有对任意精度算术的内置支持。可以安装一些非常大的插件来执行这些类型的计算,其中操作数的长度为数百到数千位。
为了娱乐,我试图在不创建大整数类的情况下在 VBA 中编写类似的函数。
我不是数学家。但我发现实现加法、减法和乘法函数相当容易。
例如,这是我添加任意大操作数的函数:
Function AddStrings$(ByVal a$, ByVal b$)
Dim carry&, i&, k&, ka&, kb&, p&, pLen&, s$, z&, subt
Const size& = 28
ka = Len(a): kb = Len(b)
Select Case kb
Case Is < ka: k = ka: If k > kb Then b = String$(k - kb, "0") & b
Case Else: k = kb: If k > ka Then a = String$(k - ka, "0") & a
End Select
s = Space$(k + 2)
p = k + 1
For i = -Int(-k / size) To 1 Step -1
p = p - size
pLen = size: If p < 1 Then p = 1: pLen = k Mod size
subt = CDec(Mid$(a, p, pLen)) + Mid$(b, p, pLen)
If carry Then subt = subt + carry
z = Len(subt)
Select Case z
Case pLen: carry = 0: Mid$(s, p, pLen) = subt
Case Is > pLen: carry = 1: Mid$(s, p, pLen) = Mid$(subt, 2)
Case Else: carry = 0: Mid$(s, p, pLen) = String$(pLen - z, "0") & subt
End Select
Next
If carry Then s = "1" & s
AddStrings = Trim$(s)
End Function
无论我给它的操作数的大小如何,这个函数似乎都能完美地工作。它将操作数分解为 28 位的块并迭代处理它们。
我的乘法程序也很完美。它使用 14 位数字块。
然而,Division 和 Mod 让我摸不着头脑。
我对加法、减法和乘法有效的策略是将操作数字符串分割成适合 VBA 本机数据类型的多个数字,并零碎地进行计算。这工作得很好,我现在可以对数百位长的字符串值进行这些计算。
但这不适用于除法或模数。
通过修补,我发现对于模数,只要除数适合本机数据类型,我就可以通过本机 Mod 函数的迭代获得任意长度的被除数并获得正确的结果。
例如,此函数适用于巨大的红利,但仅适用于长度不超过八位的除数:
Function SuperMod(ByVal a$, b$)
Do While Len(a) > 9
a = Mid$(a, 1, 9) Mod b & Mid$(a, 10)
Loop
SuperMod = a Mod b
End Function
例如:
MsgBox SuperMod("654654321902010548705495321500805040401121210900506078798456849816241968462130000051204789540453745898347543753489751261610093245892737467263468234623689898054456361110010151021101827", 99999999)
...正确显示: 84245606
但是尝试在除数中再增加一位会导致错误,因为本机 Mod 函数无法处理那么大的除数。
我的目标是找出除数可以是任意长度的方法,就像目前的除数一样。
我能够找出一种不同的方式,其中除数可以达到 15 位,并通过替换为任意大小的a Mod b被除数a - Int(a / b) * b。但是对于大于 15 位的除数,这会失败,因为此时本地除法和 Int() 函数会失败:
Function SuperMod2(ByVal a$, b$)
Do While Len(a) > 15
a = Mid$(a, 1, 15) - Int(Mid$(a, 1, 15) / b) * b & Mid$(a, 16)
Loop
SuperMod2 = a - Int(a / b) * b
End Function
此版本允许:
MsgBox SuperMod2("654654321902010548705495321500805040401121210900506078798456849816241968462130000051204789540453745898347543753489751261610093245892737467263468234623689898054456361110010151021101827", 999999999999999)
...正确显示: 194745570864677
VBA 确实支持 Variant 变量的 Decimal(28 位精度)数据子类型,但由于某种原因,这在这种情况下没有帮助。但即使这样做,它也只会扩展该方法可以处理的除数大小的大约两倍。
我可以采用什么样的数学运算来允许模数和除法的任意大小的除数?
我看不到如何对两个操作数字符串进行分块,就像我对加法、减法和乘法所做的那样,以迭代地处理结果。
我通过搜索找到的所有内容(即使在 Stack 上)都指的是大笔股息。如您所见,我已经弄清楚了。我的问题是任意大的除法器。
我非常感谢任何花时间为我指明正确方向的人。
将除数操作数分块以迭代除法是否可行?如图所示,该技术适用于加法、减法和乘法。我看不出如何使它适用于除法或 Mod 中的 DIVISOR 操作数。
如果不是,对于任意大小的除数,我还可以使用哪些其他技术?