大整数的OR乘法

时间:2009-07-02 13:40:45

标签: math biginteger

两个n位数A和B的乘法可以理解为一个移位之和:

 (A << i1) + (A << i2) + ... 

其中i1,i2,...是B中设置为1的位数。

现在让我们用OR替换PLUS以获得我真正需要的新操作:

 (A << i1) | (A << i2) | ... 

此操作非常类似于常规乘法,其中存在许多更快的算法(例如Schönhage-Strassen)。 我在这里提出了类似的操作算法吗?

数字的大小是6000位。

修改 出于某种原因,我没有链接/按钮发表评论(任何想法为什么?)所以我将编辑我的问题。 我确实为上面定义的操作搜索比O(n ^ 2)算法更快的算法。 是的,我知道这不是普通的乘法。

5 个答案:

答案 0 :(得分:1)

是否有类似的算法?我想可能不是。

有没有办法加快速度超过O(n ^ 2)?有可能。如果你认为数A是A(x)=Σa n x n 的类比,其中 n 是A的二进制数字,那么你的按位OR运算(我们称之为A⊕B)可以表示如下,其中“⇔”表示“模拟”

A⇔A(x)=Σa n x n

B⇔B(x)=Σb n x n

C =A⊕B⇔C(x)= f(A(x)B(x))= f(V(x))其中f(V(x))= f(Σv n < / sub> x n )=Σu(v n )x n 其中u(v n )= 0如果v n = 0,则u(v n )= 1。

基本上你做的相当于取两个多项式并将它们相乘,然后识别所有非零项。从位串的角度来看,这意味着将bitstring视为零或1的样本数组,convolving两个数组,并折叠非零的结果样本。有快速卷积算法是O(n log n),例如使用FFT,这里的“折叠”步骤是O(n)...但不知怎的,我想知道快速卷积的O(n log n)评估将某些东西(比如大整数的乘法)视为O(1),这样你实际上就不会得到更快的算法。无论是那个,还是增长订单的常数都是如此之大,以至于在获得任何速度优势之前,你必须拥有数千个位。 ORing非常简单。

编辑:似乎有一种称为“二进制卷积”的内容(例如,请参阅this book),这听起来非常相关,但我找不到与理论有任何良好关联它背后是否有快速算法。

编辑2:也许这个术语是“逻辑卷积”或“按位卷积”...这里是page from CPAN(bleah!)与Walsh和Hadamard一起谈论它转换是一种类似于傅里叶变换的按位...嗯,不,这似乎是XOR的模拟而不是OR。

答案 1 :(得分:0)

我认为,你问的是你给出的添加剂技术的名称 当你写“我在这里介绍的操作的类似算法吗?”......

你看过Peasant multiplication技术了吗? 如果您未在本示例中获得第3列,请阅读维基百科说明。

 B X  A
27 X  15  : 1
13    30  : 1
 6    60  : 0
 3   120  : 1
 1   240  : 1

B is 27 == binary form 11011b

27x15 = 15 + 30 + 120 + 240
      = 15<<0 + 15<<1 + 15<<3 + 15<<4
      = 405

听起来很熟悉?


这是你的算法。

  1. 选择较小的数字作为 A
    • 初始化 C 作为结果区域
    • B 不为零,
      1. 如果 B lsb1,请将 A 添加到C
    • 左移 A 一次
    • 右移 B 一次
    • C 有你的乘法结果(除非你翻过了 C 的尺寸)

  2. 更新如果您试图获得跨越6000位的移位和OR运算的快速算法,
    实际上可能有一个。我会考虑更多。

    看起来像'模糊'一个数字而不是另一个。有趣的。
    这是一个相当粗略的例子,

    110000011 X 1010101 would look like
          110000011
        110000011
      110000011
    110000011
    ---------------
    111111111111111
    

    两个数字中1的数量将决定模糊的数量,并设置所有位数。
    不知道你想用它做什么......


    Update2 这是具有两个6000位数的shift + OR运算的性质。

    1. 结果当然是12000位
      • 可以用两个比特流完成操作;但是,不必完全完成
      • 12000位流的“中间”部分几乎肯定都是 1 s(假设这两个数字都不为零)
      • 问题在于确定我们需要处理此操作以获得12000位流的两端的深度
      • 流两端的模式将取决于两个数字中存在的最大连续 1
    2. 我还没有得到一个干净的算法。已经更新了其他任何想要重新检查或远离这里的人。此外,描述这种操作的需要可能会激发人们的兴趣: - )

答案 2 :(得分:0)

您可以执行此操作O(B中A *#1位中的#1位)。

a-bitnums = set(x : ((1<<x) & A) != 0)
b-bitnums = set(x : ((1<<x) & B) != 0)

c-set = 0
for a-bit in a-bitnums:
  for b-bit in b-bitnums:
    c-set |= 1 << (a-bit + b-bit)

如果A和B的数量稀少,这可能是值得的 1位存在。

答案 3 :(得分:0)

我能做到的最好就是在循环逻辑上使用快速输出。结合使用非零方法的可能性,你可以通过检查不到2%的N ^ 2问题来回答你的问题。

下面是一些代码,它给出了80%到99%零之间的数字时序。 当数字大约为88%零时,使用它们的方法切换到更好(虽然未在下面的示例中编码)。

这不是一个高度理论化的解决方案,但它很实用。

好的,这是问题空间的一些“理论”:

基本上,X(输出)的每个位是通过沿顶部(从左到右的MSB到LSB)和沿着B的位构成的网格对角线上的位的OR求和。一侧(从上到下的MSB到LSB)。由于如果对角线上的X为1,则X为1,则可以在细胞遍历上提前执行。

下面的代码执行此操作并显示即使对于大约87%零的数字,您也只需要检查~2%的单元格。对于更密集(更多1)的数字,该百分比下降得更多。

换句话说,我不会担心棘手的算法,只是做一些有效的逻辑检查。我认为诀窍是将输出的位视为网格的对角线而不是A位移位的位与B的位。最棘手的是这种情况是跟踪你可以看到的位at A和B以及如何正确索引位。

希望这是有道理的。如果我需要进一步解释(或者如果您发现此方法有任何问题),请告诉我。

注意:如果我们更了解您的问题空间,我们可以相应地优化算法。如果你的数字大多数非零,那么这种方法比他们更好,因为他的结果是需要更多的计算和存储空间(sizeof(int)* NNZ)。

注2:这假设数据基本上是位,我使用.NET的BitArray来存储和访问数据。我不认为这会在翻译成其他语言时引起任何重大问题。基本思想仍然适用。

using System;
using System.Collections;

namespace BigIntegerOr
{
    class Program
    {
        private static Random r = new Random();

        private static BitArray WeightedToZeroes(int size, double pctZero, out int nnz)
        {
            nnz = 0;
            BitArray ba = new BitArray(size);
            for (int i = 0; i < size; i++)
            {
                ba[i] = (r.NextDouble() < pctZero) ? false : true;
                if (ba[i]) nnz++;
            }
            return ba;
        }

        static void Main(string[] args)
        {
            // make sure there are enough bytes to hold the 6000 bits
            int size = (6000 + 7) / 8;
            int bits = size * 8;

            Console.WriteLine("PCT ZERO\tSECONDS\t\tPCT CELLS\tTOTAL CELLS\tNNZ APPROACH");
            for (double pctZero = 0.8; pctZero < 1.0; pctZero += 0.01)
            {
                // fill the "BigInts"
                int nnzA, nnzB;
                BitArray a = WeightedToZeroes(bits, pctZero, out nnzA);
                BitArray b = WeightedToZeroes(bits, pctZero, out nnzB);

                // this is the answer "BigInt" that is at most twice the size minus 1
                int xSize = bits * 2 - 1;
                BitArray x = new BitArray(xSize);

                int LSB, MSB;
                LSB = MSB = bits - 1;

                // stats
                long cells = 0;
                DateTime start = DateTime.Now;

                for (int i = 0; i < xSize; i++)
                {
                    // compare using the diagonals
                    for (int bit = LSB; bit < MSB; bit++)
                    {
                        cells++;
                        x[i] |= (b[MSB - bit] && a[bit]);
                        if (x[i]) break;
                    }

                    // update the window over the bits
                    if (LSB == 0)
                    {
                        MSB--;
                    }
                    else
                    {
                        LSB--;
                    }

                    //Console.Write(".");
                }

                // stats
                TimeSpan elapsed = DateTime.Now.Subtract(start);
                double pctCells = (cells * 100.0) / (bits * bits);
                Console.WriteLine(pctZero.ToString("p") + "\t\t" +elapsed.TotalSeconds.ToString("00.000") + "\t\t" +
                    pctCells.ToString("00.00") + "\t\t" + cells.ToString("00000000") + "\t" + (nnzA * nnzB).ToString("00000000"));
            }

            Console.ReadLine();
        }
    }
}

答案 4 :(得分:0)

只需使用任何FFT多项式乘法算法,并将所有大于或等于1的结果系数转换为1。

示例:

10011 * 10001
[1 x^4 + 0 x^3 + 0 x^2 + 1 x^1 + 1 x^0] * [1 x^4 + 0 x^3 + 0 x^2 + 0 x^1 + 1 x^0]
== [1 x^8 + 0 x^7 + 0 x^6 + 1 x^5 + 2 x^4 + 0 x^3 + 0 x^2 + 1 x^1 + 1 x^0]
-> [1 x^8 + 0 x^7 + 0 x^6 + 1 x^5 + 1 x^4 + 0 x^3 + 0 x^2 + 1 x^1 + 1 x^0]
-> 100110011

有关算法的示例,请检查:

http://www.cs.pitt.edu/~kirk/cs1501/animations/FFT.html

BTW,它具有线性复杂性,即O(n log(n))

另见:

http://everything2.com/title/Multiplication%2520using%2520the%2520Fast%2520Fourier%2520Transform