为什么要使用更高的基数来实现BigInt?

时间:2012-04-16 16:33:22

标签: c++ c biginteger

我正在尝试实现BigInt并阅读了一些关于它的线程和文章,其中大多数建议使用更高的基数(256或2 ^ 32甚至2 ^ 64)。

为什么更高的基数有利于此目的?

我遇到的其他问题是我应该如何将字符串转换为更高的字符串(> 16)。我读过没有标准的方法,除了base64。最后一个问题,我如何使用这些更高的基础。一些例子会很棒。

2 个答案:

答案 0 :(得分:8)

用于乘以或添加适合寄存器的数字的CPU周期往往是相同的。因此,通过使用整个寄存器,您将获得最少的迭代次数和最佳性能。也就是说,在32位架构上,使基本单元为32位,在64位架构上,使其为64位。否则 - 比方说,如果你只填满32位寄存器的8位 - 你就是在浪费周期。

答案 1 :(得分:2)

  1. 第一个答案说得最好。我个人使用base 2 ^ 16来防止乘法溢出。这允许任何两个数字一起乘以一次而不会溢出。

  2. 转换为更高的基数需要快速分割方法以及尽可能地打包数字(假设你的BigInt lib可以处理多个碱基)。

  3. 考虑基数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
    
    1. ???
    2. 你应该有一个Base类来存储toString的字母+大小。如果Base无效,则只需在逗号分隔列表中显示数字。

      你所有的方法都应该使用BigInt的当前基础,而不是一些常量。

      这就是全部?

      从那里,你将能够做到像

      这样的事情
      BigInt i = BigInt.convertString("1234567", Base["0123456789"])
      

      []重载的地方,将创建一个新的基础或返回已经创建的基础。

      您还可以执行

      之类的操作
      i.toString()
      i.base = Base["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
      i.base = 256
      i.base = 45000
      

      etc ^ _ ^。

      另外,如果你使用整数并希望能够返回BigInt余数,则除法可能会有点棘手= P,但它仍然很容易^ _ ^。

      This is a BigInt library I coded in vjass (yes, for Warcraft 3, lol, don't judge me)

      TriggerEvaluate(evalBase)之类的东西只是为了防止线程崩溃(邪恶的操作限制)。

      祝你好运:D