使用Python實現多項式係數卷積乘法

關鍵字

多項式乘法 卷積乘法 Python 多項式係數 卷積係數 複數多項式 華爲機考 算法

問題來源

來源於一個華爲面試題。題目內容大致如下:

題目描述

多項式 的係數[b(2) b(1) b(0)]=[1 2 5]
二者相乘所得的多項式 的係數[c(3) c(2) c(1) c(0)]=[1 3 7 5]
利用上面的計算方法,我們很容易得到:
c(0)=a(0)b(0)
c(1)=a(0)b(1)+a(1)b(0)
c(2)=a(0)b(2)+a(1)b(1)+a(2)b(0)
c(3)=a(0)b(3)+a(1)b(2)+a(2)b(1)+a(3)b(0)
其中:a(3)=a(2)=b(3)=0
在上面的基礎上推廣一下:
假定兩個多項式的係數分別爲a(n),n=0n1和b(n),n=0n2,這兩個多項式相乘所得的多項式係數爲c(n),則:
c(0)=a(0)b(0)
c(1)=a(0)b(1)+a(1)b(0)
c(2)=a(0)b(2)+a(1)b(1)+a(2)b(0)
c(3)=a(0)b(3)+a(1)b(2)+a(2)b(1)+a(3)b(0)
c(4)=a(0)b(4)+a(1)b(3)+a(2)b(2)+a(3)b(1)+a(4)b(0)
以此類推可以得到卷積算法:
上面這個式子就是a(n)和b(n)的卷積表達式。
通常我們把a(n)和b(n)的卷積記爲:a(n)b(n),其中的表示卷積運算符

輸入描述

兩個最高階數爲4的複數多項式係數序列。高階係數先輸入;每個係數爲複數,複數先輸入實數部分,再輸入虛數部分; 實部或者虛部爲0,則輸入爲0;
每個實部和虛部的係數最大值不超過1000

輸出描述

求卷積多項式係數輸出;先輸出高階係數,多項式算法.
輸出的期望結果是多項式乘積結果,因爲自己的算法研究的不太深入,所以膚淺地瞭解到這個可以稱之爲卷積。

測試Demo

輸入:

1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1

輸出

0
2
0
4
0
6
0
8
0
10
0
8
0
6
0
4
0
2

思路和代碼

方法一(數學邏輯)

思路:

利用純數學邏輯,兩個多項式相乘,是兩個多項式的每個係數和另一個多項式的係數循環遍歷相乘,並將次數相同的係數合併。

代碼:

import time


# 定義兩個多階多項式的階數,即每個多項式的最高次冪
# 因爲冪次的變化,決定終端輸入係數的個數。 此處也可以使用配置文件操作。
A_LEVEL = 4
B_LEVEL = 4


def get_plural_product(sub_as, sub_bs, an, bn):
    """
    計算兩個複數乘積,返回乘積結果的冪次,以及結果的實部和虛部的係數。
    :param sub_as: 列表,第一個複數的兩個係數
    :param sub_bs: 列表,第二個複數的兩個係數
    :param an: 第一個複數帶上的參數的冪次
    :param bn: 第二個複數帶上的參數的冪次
    :return: 列表,0元素爲結果值的冪次,1元素爲實數部分結果,2元素爲虛數部分結果
    """
    return [an+bn, (sub_as[0] * sub_bs[0] - sub_as[1] * sub_bs[1]),
            (sub_as[0] * sub_bs[1] + sub_as[1] * sub_bs[0])]


def update_plural_list(arr_mul, add_one):
    """
    將兩個複數的乘積係數,添加到結果列表中。
    :param arr_mul: 結果列表,是列表型列表。列表中包含 (A_LEVEL + B_LEVEL + 1)
                    個子列表;   子列表的格式大概是[n, a, b]形式,n代表次數,a代表n
                    冪次的實部係數,b代表n冪次的虛部係數。
    :param add_one: 遍歷過程或得的臨時的兩個複數乘積的結果,結果也是[n, a, b]形式
    :return: 更新的結果列表,將arr_mul中子列表的同add_one冪次相同的參數進行了相加操作。
    """
    for a in arr_mul:
        if a[0] == add_one[0]:
            a[1] += add_one[1]
            a[2] += add_one[2]
            break
    # 這裏的另外一個優化的方式是可以使用字典進行尋值。


def get_multi_product(arr_a, arr_b):
    """
    獲取複數多項式的乘積
    :param arr_a: 第一個複數多項式的係數列表,列表格式爲
        [最高次實部,最高次虛部,次高次實部,次高次虛部, ......, 0次實部,0次虛部]
    :param arr_b: 第二個複數多項式列表
    :return: 無,按照從高次冪到低次冪,從實部到虛部順序打印結果係數。
    """
    global A_LEVEL
    global B_LEVEL

    # 獲取結果最高次冪數
    top_level = A_LEVEL + B_LEVEL

    # 創建初始結果列表,格式應該爲:
    # [[n, 0, 0], [n-1, 0, 0], [n-2, 0, 0], ..., [0, 0, 0]]
    # 其中 n = (A_LEVEL + B_LEVEL), 最高次冪數。
    # 子列表的 0索引位置爲冪次。1索引位置爲當前冪次的實數係數,2索引位置爲虛數係數。
    res_arr = list()
    for i in range(top_level+1)[::-1]:
        res_arr.append([i, 0, 0])
    # print("初始結果列表爲: {}".format(res_arr))
    # 初始結果格式爲: [[n, 0, 0], [n-1, 0, 0], [n-2, 0, 0], ..., [0, 0, 0]]

    # 將原始係數列表從最高次冪到最低次冪,從實部到虛部格式的一維繫數列表轉換爲二位列表
    # 即: 將 [an, ani, ..., a0, a0i]  轉換爲: [[an, ani], ..., [a0, a0i]]
    # 轉換爲列表型列表。子列表對應每個冪次的實數和虛數部分的係數。
    arr_a_new = [arr_a[i:i+2] for i in range(0, len(arr_a), 2)]
    arr_b_new = [arr_b[i:i+2] for i in range(0, len(arr_b), 2)]
    print("更新多項式一系數結果列表: {}".format(arr_a_new))
    print("更新多項式二係數結果列表: {}".format(arr_b_new))

    for i in range(len(arr_a_new)):
        for j in range(len(arr_b_new)):
            res = get_plural_product(
                arr_a_new[i], arr_b_new[j],
                len(arr_a_new)-1-i, len(arr_b_new)-1-j)
            update_plural_list(res_arr, res)

    for ra in res_arr:
        print(ra[1])
        print(ra[2])


def main():
    """ Main function """
    global A_LEVEL
    global B_LEVEL

    # 定義兩個多項式的係數列表
    a_arr = list()
    b_arr = list()

    # 從終端輸入兩個多項式的係數,並添加到對應的列表中
    # 注意係數的輸入原則:
    # 先輸入第一個多項式的所有係數,再輸入第二個多項式的所有係數
    # 係數的次數從最高次到最低次, 係數先輸入實數部分,再輸入虛數部分
    for i in range((A_LEVEL+1) * 2):
        a_arr.append(int(input()))
    for i in range((B_LEVEL+1) * 2):
        b_arr.append(int(input()))

    start_t = time.time()
    # 調用函數,打印結果
    get_multi_product(a_arr, b_arr)
    print("數據處理消耗時間: {}".format(time.time() - start_t))

    print("Done!!")


if __name__ == "__main__":
    main()

方法二(算法邏輯)

思路:

利用卷積算法原理,結果中的n冪次係數爲兩個多項式中的x冪次和y冪次的乘積,其中:x+y=n.

代碼:

參考:
第二題 多項式卷積乘法
在代碼的基礎上做了些註釋和簡單修改。

import time


A_LEVEL = 4
B_LEVEL = 4


def juanji():
    """
    輸入兩個多階項式的實部和虛部的係數,從高次到低次,從實部到虛數順序輸入
    :return:  打印兩個多階多項式卷積結果係數。順序同輸入規則。
    """
    global A_LEVEL
    global B_LEVEL

    # 初始化兩個多項式的係數列表
    a_xishu = list()
    b_xishu = list()
    for i in range(A_LEVEL+1):
        one = list()
        one.append(int(input()))
        one.append(int(input()))
        a_xishu.append(one)

    for i in range(B_LEVEL+1):
        two = list()
        two.append(int(input()))
        two.append(int(input()))
        b_xishu.append(two)

    # 這個轉換很重要,利用了冪次和列表索引的聯繫,通過逆序轉換,冪次和列表索引一致
    a_xishu = a_xishu[::-1]
    b_xishu = b_xishu[::-1]

    star_t = time.time()
    a_len = len(a_xishu)
    b_len = len(b_xishu)
    top_level = A_LEVEL + B_LEVEL
    for i in range(top_level+1)[::-1]:
        ci_s = 0
        ci_x = 0
        for index in range(i + 1)[::-1]:
            if i - index < a_len and index < b_len:
                temp = fushumulity(a_xishu[i - index], b_xishu[index])
                ci_s += temp[0]
                ci_x += temp[1]

        print(ci_s)
        print(ci_x)

    print("數據處理耗時: {}".format(time.time()-star_t))


def fushumulity(x, y):
    s = x[0] * y[0] - x[1] * y[1]
    x = x[0] * y[1] + x[1] * y[0]

    return s, x


juanji()

聯繫我

如果有什麼疑問,可以聯繫探討![email protected]

發佈了1 篇原創文章 · 獲贊 1 · 訪問量 238
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章