0

「畳み込みは周波数領域での乗算」ですが、文字通りの乗算でもあるようです。たとえば、メモリ内の数字を並べてリストに隣接させると、次のようになります。

5:  (byte) 00000101
22: (byte) 00010110
7:  (byte) 00000111
8:  (byte) 00001000

Becomes:

(Int32) 00000101000101100000011100001000

次に、この結果のリスト/数値を別のそのようなリストで乗算すると、結果は一方のリストと他方のリストの畳み込みになります。次の C# プログラムは、これを示しています。

using System;

public class Program
{
    public static void Main(string[] args)
    {
        var A = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
        var a = combine_to_Int64(A);
        var B = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
        var b = combine_to_Int64(B);
        var c = a * b;
        var C = separate_to_8_byte(c);
        var d = deconvolution(c, b); // not correct
        var D = separate_to_8_byte(d);
        Console.WriteLine(
            "The convolution of (" + to_string(A) + ") with ("
            + to_string(B) + ") is: (" + to_string(C) + ")");
        Console.WriteLine(
            "The deconvolution of (" + to_string(C) + ") with ("
            + to_string(B) + ") is: (" + to_string(D) + ")");
    }

    public static Int64 convolution(Int64 a, Int64 b)
    {
        return a * b;
    }

    private static Int64 combine_to_Int64(byte[] n)
    {
        if (n.Length == 4)
            return n[0] + 65536 * n[1] + 4294967296 * n[2] +
                281474976710656 * n[3];
        else if (n.Length == 8)
            return n[0] + 256 * n[1] + 65536 * n[2] + 16777216 * n[3] +
                4294967296 * n[4] + 1099511627776 * n[5] +
                281474976710656 * n[6] + 72057594037927936 * n[7];
        else
            throw new ArgumentException();
    }

    private static Int16[] separate_to_4_Int16(Int64 a)
    {
        return new []{(Int16) a, (Int16) (a >> 0x10),
            (Int16) (a >> 0x20), (Int16) (a >> 0x30)};
    }

    private static byte[] separate_to_8_byte(Int64 a)
    {
        return new []{(byte) a, (byte) (a >> 8), (byte) (a >> 0x10),
            (byte) (a >> 0x18), (byte) (a >> 0x20), (byte) (a >> 0x28),
            (byte) (a >> 0x30), (byte) (a >> 0x38)};
    }

    public static string to_string(byte[] values)
    {
        string s = "";
        foreach (var val in values)
            s += (s == "" ? "" : " ") + val;
        return s;
    }

    public static string to_string(Int16[] values)
    {
        string s = "";
        foreach (var val in values)
            s += (s == "" ? "" : " ") + val;
        return s;
    }

    // ---

    public static Int64 deconvolution(Int64 a, Int64 b)
    {
        var large = System.Numerics.BigInteger.Parse(
            "1000000000000000000000000000000");
        return (Int64)(((
            (new System.Numerics.BigInteger(a) * large)
            / new System.Numerics.BigInteger(b))
            * 72057594037927936) / large);
    }
}

次のコードを試してください: rextester.com/YPKFA14408

出力は次のとおりです。

The convolution of (1 2 3 4 5 6 7 8) with (1 2 3 4 5 6 7 8) is: (1 4 10 20 35 56 84 120)

The deconvolution of (1 4 10 20 35 56 84 120) with (1 2 3 4 5 6 7 8) is: (219 251 194 172 10 94 253 14)

出力の最初の行が正しいことを示すデモは、https ://oeis.org/A000292 にあります。

「整数列のオンライン百科事典」…「四面体(または三角錐)数」…「自然数とそれ自体の畳み込み。-フェリックス・ゴールドバーグ」


Q: 提供されたコードのデコンボリューション関数、または結果がどうあるべきかについての私の理解の何が問題になっていますか?

4

1 に答える 1

1

違いはキャリーです。

入力を多項式として扱います...

00000101 becomes x^2 + x^0
00000111 becomes x^2 + x^1 + x^0

多項式の乗算と畳み込みはまったく同じ操作です (遅延の z 変換プリミティブである-1xとします...結局、乗算は変換ドメインで行われます)。z

しかし、桁上げがあるため、算術乗算は多項式乗算と同じではありません。結果として

(x^1 + x^0) * (x^1 + x^0)

x^2 + 2 x^1 + x^0

そして確かに畳み込み

conv([1 1], [1 1]) = [1 2 1]

しかし

0011 * 0011

同様に

0100 + 2 * 0010 + 0001

算術では、2 * 0010となり0100、最終結果は

1001

キャリーが行われるため、畳み込み (多項式乗算) とはまったく異なります。

算術結果はx = 2... の場合にのみ保持されますが、畳み込みでは時間遅延演算子でx なければなりません。

それぞれが 1 つの時間サンプルの振幅を表す 8 ビットのグループで作業している場合、同じ効果が発生します。グループ内の算術演算は問題ありませんが、グループの境界を越えるキャリーがあるとすぐに、畳み込みと乗算の同等性が失われます。

于 2017-01-02T20:24:38.877 に答える