Görünüşe göre bu O (n lg n) çarpma algoritmasında hata nerede?


15

Güncel bir bulmaca blog yazısı üç eşit aralıklı olanları bulma konusunda bir götürebilir stackoverflow soru iddiaları O (n lg n) zamanında bunu yapmak için bir üst cevap. İlginç olan, çözümün bir polinomun karesini içermesi ve O (n lg n) zamanında nasıl yapılacağını açıklayan bir makaleye gönderme yapmasıdır .

Şimdi, polinomları çoğaltmak pratik olarak sayıları çoğaltmakla aynıdır. Tek gerçek fark, taşıma eksikliğidir. Ancak ... taşıma işlemleri O (n lg n) zamanda da yapılabilir. Örneğin:

    var value = 100; // = 0b1100100

    var inputBitCount = value.BitCount(); // 7 (because 2^7 > 100 >= 2^6)
    var n = inputBitCount * 2; // 14
    var lgn = n.BitCount(); // 4 (because 2^4 > 14 => 2^3)
    var c = lgn + 1; //5; enough space for 2n carries without overflowing

    // do apparently O(n log n) polynomial multiplication
    var p = ToPolynomialWhereBitsAreCoefficients(value); // x^6 + x^5 + x^2
    var p2 = SquarePolynomialInNLogNUsingFFT(p); // x^12 + 2x^11 + 2x^10 + x^8 + 2x^7 + x^4
    var s = CoefficientsOfPolynomial(p2); // [0,0,0,0,1,0,0,2,1,0,2,2,1]
    // note: s takes O(n lg n) space to store (each value requires at most c-1 bits)

    // propagate carries in O(n c) = O(n lg n) time
    for (var i = 0; i < n; i++)
        for (var j = 1; j < c; j++)
            if (s[i].Bit(j))
                s[i + j].IncrementInPlace();

    // extract bits of result (in little endian order)
    var r = new bool[n];
    for (var i = 0; i < n; i++)
        r[i] = s[i].Bit(0);

    // r encodes 0b10011100010000 = 10000

Benim sorum şu: burada hata nerede? O (n lg n) 'de sayıları çarpmak bilgisayar biliminde devasa bir açık problemdir ve cevabın bu kadar basit olacağından gerçekten şüpheliyim.

  • Taşıma yanlış mı değil O (n lg n) mı? Değer başına lg n + 1 biti taşımak için yeterli olduğunu ve algoritmanın çok basit olduğunu, yanlış olsaydı şaşırırdım. Her ne kadar ayrı bir artış O (lg n) zaman alabilse de, x artışlar için toplam maliyetin O (x) olduğunu unutmayın.
  • Kağıttan polinom çarpma algoritması yanlış mı yoksa ihlal ettiğim koşullar mı var? Makale, sayı teorik bir dönüşüm yerine hızlı bir fourier dönüşümü kullanıyor.
  • Birçok akıllı insan 40 yıldır Schönhage-Strassen algoritmasının belirgin bir varyantını kaçırdı mı? Bu en az muhtemel görünüyor.

Aslında verimli polinom çarpma dışında bunu uygulamak için kod yazdım (henüz yeterince teorik dönüşüm yeterince anlamıyorum). Rastgele test, algoritmanın doğru olduğunu onaylar gibi görünür, bu nedenle sorun zaman karmaşıklığı analizinde olabilir.


Meydan içermemeli x^10 + 2x^8mi? x ^ 10 yalnızca bir kez (x ^ 5 * x ^ 5) ve x ^ 8 iki kez (x ^ 6 * x ^ 2 + x ^ 2 * x ^ 6)
Sjoerd

Örneği elle yaptım. Aritmetik bir hata yaptım. Afedersiniz. Aslında algoritmayı uyguladım, test ettim ve doğru sonuçları aldım.
Craig Gidney

Yanıtlar:



1

Buradaki "hata", bir Fourier dönüşümünün, dönüştürülecek sayıları toplama veya çarpma işleminin O (n log n) adımlarında hesaplanabilmesidir, ancak n gerçekten büyüdükçe, dönüştürülen sayılar da büyür. başka bir faktör günlüğü günlüğü

Uygulamada, FFT'de dört hassas kayan nokta (128 bit kayan nokta) veya 128 bit sabit nokta kullanmanın, hesaplanacak kadar küçük herhangi bir ürün için yeterli olacağını düşünürüm.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.