为什么要使用更高的基数来实现BigInt?
我正在尝试实现BigInt并阅读了一些关于它的线程和文章,其中大多数建议使用更高的基数(256或2 ^ 32甚至2 ^ 64)。
为什么更高的基数有利于此目的?
我有的其他问题是我应该如何将字符串转换为更高的基数(> 16)。 我读过没有标准的方法,除了base64。 最后一个问题,我如何使用这些更高的基础。 一些例子会很棒。
用于乘以或添加适合寄存器的数字的CPU周期往往是相同的。 因此,通过使用整个寄存器,您将获得最少的迭代次数和最佳性能。 也就是说,在32位架构上,使基本单元为32位,在64位架构上,使其为64位。 否则 – 比方说,如果你只填满32位寄存器的8位 – 你就是在浪费周期。
-
第一个答案说得最好。 我个人使用base 2 ^ 16来防止乘法溢出。 这允许任何两个数字一起乘以一次而不会溢出。
-
转换到更高的基数需要快速除法方法以及尽可能地打包数字(假设你的BigInt lib可以处理多个基数)。
考虑基数10 – >基数2.实际转换将是10 – > 10000 – > 32768 – > 2.这可能看起来更慢,但从基数10转换为10000非常快。 在10000和32768之间进行转换的迭代次数非常快,因为迭代的数字非常少。 打开32768到2的包装也非常快。
因此,首先将基地打包到它可以去的最大基地。 为此,只需将数字组合在一起即可。 此基数应<= 2 ^ 16以防止溢出。
接下来,将数字组合在一起,直到它们> =目标基数。 从这里,使用快速划分算法除以目标基数,该算法通常会在任何其他场景中溢出。
一些快速代码
if (!packed) pack() from = remake() //moves all of the digits on the current BigInt to a new one, O(1) loop addNode() loop remainder = 0 remainder = remainder*fromBase + from.digit enter code here`exitwhen remainder >= toBase set from = from.prev exitwhen from.head if (from.head) node.digit = remainder else node.digit = from.fastdiv(fromBase, toBase, remainder) exitwhen from.head
看看快速划分
loop digit = remainder/divide remainder = remainder%divide //gather digits to divide again loop this = prev if (head) return remainder remainder = remainder*base + digit exitwhen remainder >= divide digit = 0 return remainder
最后,如果你打开包装,请打开包装
打包只是将数字组合在一起。
基数10到基数10000的例子
4th*10 + 3rd *10 + 2nd *10 + 1st
- ???
你应该有一个Base类来存储toString的字母+大小。 如果Base无效,则只需在逗号分隔列表中显示数字。
你的所有方法都应该使用BigInt的当前基础,而不是一些常量。
就这样?
从那里,你将能够做到这样的事情
BigInt i = BigInt.convertString("1234567", Base["0123456789"])
[]重载的地方,将创建一个新的基数或返回已创建的基数。
你也可以做类似的事情
i.toString() i.base = Base["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"] i.base = 256 i.base = 45000
等^ ^ ^。
此外,如果你使用整数并且你想能够返回BigInt余数,则除法可能会有点棘手= P,但它仍然很容易^ _ ^。
这是我用vjass编写的BigInt库(是的,对于魔兽争霸3,哈哈,不要评判我)
像TriggerEvaluate(evalBase)
类的东西只是为了防止线程崩溃(恶意操作限制)。
祝你好运:D