Math 还是大整数的乘法

Math 还是大整数的乘法,math,biginteger,Math,Biginteger,两个n位数字A和B的相乘可以理解为移位之和: (A << i1) + (A << i2) + ... (A有类似的算法吗?我想可能没有 有没有办法加快O(n 2)以外的事情?可能。如果你认为A是A(x)=yxn的类似物,阿纳尔的二进制数字是A,那么你就用bitwise ORs(我们称之为A)进行运算。⊕ B)可表示如下,其中“⇔" 表示“模拟” A⇔ A(x)=∑anxn B⇔ B(x)=∑bnxn C=A⊕ B⇔ C(x)=f(A(x)B(x))=f(V(x)),

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

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

(A有类似的算法吗?我想可能没有

有没有办法加快O(n 2)以外的事情?可能。如果你认为A是A(x)=yxn的类似物,阿纳尔的二进制数字是A,那么你就用bitwise ORs(我们称之为A)进行运算。⊕ B)可表示如下,其中“⇔" 表示“模拟”

A⇔ A(x)=∑anxn

B⇔ B(x)=∑bnxn

C=A⊕ B⇔ C(x)=f(A(x)B(x))=f(V(x)),其中f(V(x))=f(∑vnxn)=∑u(vn)xn其中,如果vn=0,则u(vn)=0,否则u(vn)=1

基本上,你要做的是将两个多项式相乘,然后识别所有的非零项。从位字符串的角度来看,这意味着将位字符串视为一个由0或1组成的样本数组,这两个数组,并折叠得到的非零样本。有快速卷积算法例如,使用FFT,这里的“折叠”步骤是O(n)…但不知何故,我想知道快速卷积的O(n logn)计算是否将某些东西(如大整数的乘法)视为O(1)所以你实际上不会得到一个更快的算法。或者说,或者增长阶的常数太大,你必须有数千位才能获得速度优势。ORing是如此简单

编辑:这里似乎有一种叫做“二进制卷积”(参见示例)的东西听起来非常相关,但我找不到它背后的理论以及是否有快速算法的良好链接


编辑2:可能术语是“逻辑卷积”或“位卷积”…这里有一个(bleah!)和沃尔什变换和阿达玛变换一起讨论一下,这两种变换在某种程度上等同于傅里叶变换……嗯,不,这似乎是对异或的模拟,而不是对或的模拟。

我想,您是在问您所给出的加法技术的名称
当你写“我在这里介绍的运算有类似的算法吗?”

你看过这项技术了吗?
如果本例中没有第三列,请阅读维基百科的描述

 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
s的数量将决定对一个设置了所有位的数字的模糊程度。
想知道你想用它做什么


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

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

    你可以这样做O(#a中的1位*#B中的1位)


    a-bitnums=set(x:((1我能想到的最好方法是在循环逻辑上使用快速输出。结合使用themis所述的非零方法的可能性,您可以通过检查不到2%的N^2问题来回答您的问题

    下面是一些代码,给出了介于80%和99%零之间的数字的计时。 当数字在88%左右为零时,使用themis的方法会变得更好(尽管下面的示例中没有编码)

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

    好的,这里有一些关于问题空间的“理论”:

    基本上,X(输出)的每个位都是网格对角线上的位的或和,网格是由a的位沿顶部(MSB到LSB从左到右)和B的位沿侧面(MSB到LSB从上到下)构成的。由于X的位为1(如果对角线上的任何位为1),因此您可以在单元遍历中执行早期输出

    下面的代码说明了这一点,即使对于约87%为零的数字,您也只需检查约2%的单元格。对于密度更高(1更多)的数字,该百分比的下降幅度更大

    换句话说,我不会担心复杂的算法,只需要做一些有效的逻辑检查。我认为诀窍是将输出的位看作网格的对角线,而不是移位的位或B的位。最棘手的事情是跟踪A和B中的位,以及如何正确地进行无损检测

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

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

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

    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();
            }
        }
    }
    
    使用系统;
    使用系统集合;
    名称空间大整数
    {
    班级计划
    {
    私有静态随机r=新随机();
    专用静态位数组加权子线程(整数大小,双pctZero,输出整数nnz)
    {
    nnz=0;
    BitArray ba=新的BitArray(大小);
    对于(int i=0;i110000011 X 1010101 would look like
          110000011
        110000011
      110000011
    110000011
    ---------------
    111111111111111
    
    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)
    
    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();
            }
        }
    }
    
    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