1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        淺談乘法

        共 4060字,需瀏覽 9分鐘

         ·

        2022-01-09 13:29

        本文簡(jiǎn)要介紹快速冪、快速乘等算法,并與取模運(yùn)算進(jìn)行結(jié)合

        abstract.png

        快速冪

        所謂快速冪,指的是快速計(jì)算冪的方法。例如計(jì)算3的23次冪,如果采用樸素的方式一次一次地乘3,需要進(jìn)行22次。其時(shí)間復(fù)雜度為線(xiàn)性時(shí)間。而如果轉(zhuǎn)換思路,我們將指數(shù)的23改為采用二進(jìn)制表示:10111。如下所示,可以看到,變成若干個(gè)乘數(shù)(即下圖的3的1次方、3的2次方、3的4次方、3的16次方)進(jìn)行相乘。其中每個(gè)乘數(shù)是前一個(gè)乘數(shù)的平方。特別地,對(duì)于指數(shù)相應(yīng)二進(jìn)制位為0的乘數(shù)(例如下圖紅框中3的8次方),則在最終計(jì)算過(guò)程中直接跳過(guò)即可??梢钥吹?,快速冪的時(shí)間復(fù)雜度為對(duì)數(shù)時(shí)間

        figure 1.jpeg

        Java版本實(shí)現(xiàn)如下所示

        /**
        ?*?快速冪
        ?*?@param?base?底數(shù)
        ?*?@param?exp?指數(shù)
        ?*?@return
        ?*/

        public?static?long?quickPower(long?base,?long?exp)?{
        ????//?乘法單位元為1
        ????long?result?=?1;
        ????long?temp?=?base;
        ????while?(exp!=0)?{
        ????????//?取出指數(shù)在二進(jìn)制下的最后一位
        ????????long?lastBit?=?exp&1;
        ????????//?該位不為0,?說(shuō)明最終計(jì)算結(jié)果需要乘上這個(gè)中間乘數(shù)
        ????????if(?lastBit!=0?)?{
        ????????????result?*=?temp;
        ????????}
        ????????//?更新中間乘數(shù)
        ????????temp?*=?temp;
        ????????//?移除指數(shù)在二進(jìn)制下的最后一位
        ????????exp?>>=?1;
        ????}
        ????return?result;
        }

        模冪運(yùn)算

        在快速冪的基礎(chǔ)上,我們來(lái)看下如何進(jìn)行模冪運(yùn)算。即形如“(x^y) mod z”。在進(jìn)一步展開(kāi)前,我們先介紹下模在乘法下的運(yùn)算規(guī)則

        //?乘積的模?等于?各乘數(shù)分別取模后求積、并對(duì)積再取一次模
        (a·b)?mod?z?=?[(a?mod?z)·(b?mod?z)]?mod?z

        這里,我們以(3^23)mod 7 為例進(jìn)行說(shuō)明。結(jié)合快速冪、模運(yùn)算規(guī)則進(jìn)行轉(zhuǎn)換如下所示,可以看到轉(zhuǎn)換后的各乘數(shù)X實(shí)際上是對(duì)前一個(gè)X的平方再取模的結(jié)果,體現(xiàn)在下述代碼的(2)處

        figure 2.jpeg

        這里我們令X1~X4乘積后進(jìn)行取模的結(jié)果為A4,再次運(yùn)用模運(yùn)算規(guī)則進(jìn)行轉(zhuǎn)換。由于X4肯定小于7,故X4 mod 7 可以直接化簡(jiǎn)為X4。同時(shí)令X1~X3乘積后進(jìn)行取模的結(jié)果為A3??梢钥吹狡浣沂玖宋覀?cè)诤竺孢M(jìn)行迭代計(jì)算過(guò)程中的遞推公式,體現(xiàn)在下述代碼的(1)處

        figure 3.jpeg

        此時(shí),我們就可以利用快速冪實(shí)現(xiàn)模冪運(yùn)算,Java實(shí)現(xiàn)如下所示

        /**
        ?*?模冪運(yùn)算
        ?*?@param?base?底數(shù)
        ?*?@param?exp?指數(shù)
        ?*?@param?n?模
        ?*?@return
        ?*/

        public?static?long?modPower(long?base,?long?exp,?long?n)?{
        ????//?乘法單位元為1
        ????long?result?=?1;
        ????//?即公式中的X1
        ????long?temp?=?base?%?n;
        ????while?(exp!=0)?{
        ????????//?取出指數(shù)在二進(jìn)制下的最后一位
        ????????long?lastBit?=?exp&1;
        ????????//?該位不為0,?說(shuō)明最終計(jì)算結(jié)果需要乘上這個(gè)中間乘數(shù)
        ????????if(?lastBit!=0?)?{
        ????????????//?此處應(yīng)用迭代計(jì)算過(guò)程的遞推公式
        ????????????result?=?(result?*?temp)?%?n;??//?(1)
        ????????}
        ????????//?更新中間乘數(shù):?對(duì)前一個(gè)乘數(shù)進(jìn)行平方再取模
        ????????temp?=?(temp?*?temp)?%?n;???//?(2)
        ????????//?移除指數(shù)在二進(jìn)制下的最后一位
        ????????exp?>>=?1;
        ????}
        ????return?result;
        }

        快速乘

        介紹完快速冪,相應(yīng)的快速乘就簡(jiǎn)單很多了。其基本原理也是類(lèi)似的,將其中的一個(gè)乘數(shù)按二進(jìn)制進(jìn)行拆分,然后利用分配律將乘法轉(zhuǎn)換為加法??梢钥吹?,一方面,對(duì)于兩個(gè)大數(shù)相乘的場(chǎng)景,快速乘通過(guò)將乘法變?yōu)榧臃ù蟠筇岣咂湓谟?jì)算機(jī)中的運(yùn)算效率;另一方面,對(duì)于大數(shù)的模乘運(yùn)算而言,形如“(x·y) mod z”。借助快速乘可以防止兩個(gè)大數(shù)的乘積直接溢出。典型地,模乘運(yùn)算廣泛存在于RSA計(jì)算當(dāng)中

        例如計(jì)算3x23,我們將其中一個(gè)乘數(shù)23改為采用二進(jìn)制表示:10111,然后采用乘法的分配律將其改寫(xiě)加法。類(lèi)似地,可以看到各加數(shù)均是前一個(gè)加數(shù)的兩倍

        figure 4.jpeg

        Java實(shí)現(xiàn)如下所示

        /**
        ?*?快速乘
        ?*?@param?num1?乘數(shù)1
        ?*?@param?num2?乘數(shù)2
        ?*?@return
        ?*/

        public?static?long?quickMultiply(long?num1,?long?num2)?{
        ????//?加法單位元為0
        ????long?result?=?0;
        ????long?temp?=?num1;
        ????while?(num2!=0)?{
        ????????//?取出num2在二進(jìn)制下的最后一位
        ????????long?lastBit?=?num2&1;
        ????????//?該位不為0,?說(shuō)明最終計(jì)算結(jié)果需要加上這個(gè)中間數(shù)
        ????????if(?lastBit!=0?)?{
        ????????????result?+=?temp;
        ????????}
        ????????//?更新中間數(shù)
        ????????temp?+=?temp;
        ????????//?移除指數(shù)在二進(jìn)制下的最后一位
        ????????num2?>>=?1;
        ????}
        ????return?result;
        }

        模乘運(yùn)算

        在快速乘的基礎(chǔ)上,我們來(lái)看下如何進(jìn)行模乘運(yùn)算。即形如“(x·y) mod z”。在進(jìn)一步展開(kāi)前,我們先介紹下模在加法下的運(yùn)算規(guī)則

        //?和的模?等于?各數(shù)分別取模后求和、并對(duì)和再取一次模
        (a+b)?mod?z?=?[(a?mod?z)+(b?mod?z)]?mod?z

        這里,我們以(3x23)mod 7 為例進(jìn)行說(shuō)明。結(jié)合快速乘、模運(yùn)算規(guī)則進(jìn)行轉(zhuǎn)換如下所示,可以看到轉(zhuǎn)換后的各加數(shù)X實(shí)際上是前一個(gè)X的兩倍再取模的結(jié)果,體現(xiàn)在下述代碼的(2)處

        figure 5.jpeg

        這里我們令X1~X4之和進(jìn)行取模的結(jié)果為A4,再次運(yùn)用模運(yùn)算規(guī)則進(jìn)行轉(zhuǎn)換。由于X4肯定小于7,故X4 mod 7 可以直接化簡(jiǎn)為X4。同時(shí)令X1~X3之和進(jìn)行取模的結(jié)果為A3??梢钥吹狡浣沂玖宋覀?cè)诤竺孢M(jìn)行迭代計(jì)算過(guò)程中的遞推公式,體現(xiàn)在下述代碼的(1)處

        figure 6.jpeg

        此時(shí),我們就可以利用快速乘實(shí)現(xiàn)模乘運(yùn)算,Java實(shí)現(xiàn)如下所示

        /**
        ?*?模乘運(yùn)算
        ?*?@param?num1?乘數(shù)1
        ?*?@param?num2?乘數(shù)2
        ?*?@param?n?模
        ?*?@return
        ?*/

        public?static?long?modMultiply(long?num1,?long?num2,?long?n)?{
        ????//?加法單位元為0
        ????long?result?=?0;
        ????//?即公式中的X1
        ????long?temp?=?num1?%?n;
        ????while?(num2!=0)?{
        ????????//?取出num2在二進(jìn)制下的最后一位
        ????????long?lastBit?=?num2&1;
        ????????//?該位不為0,?說(shuō)明最終計(jì)算結(jié)果需要加上這個(gè)中間數(shù)
        ????????if(?lastBit!=0?)?{
        ????????????//?此處應(yīng)用迭代計(jì)算過(guò)程遞推公式
        ????????????result?=?(result?+?temp)?%?n;???//(1)
        ????????}
        ????????//?更新中間數(shù):?對(duì)前一個(gè)數(shù)翻倍再取模
        ????????temp?=?(temp+temp)?%?n;?//?(2)
        ????????//?移除指數(shù)在二進(jìn)制下的最后一位
        ????????num2?>>=?1;
        ????}
        ????return?result;
        }

        矩陣快速冪

        前面我們提到了快速冪,故這里就矩陣的快速冪作一下補(bǔ)充說(shuō)明。首先,對(duì)于矩陣形式的快速冪而言,其與普通的快速冪在基本原理上沒(méi)有差別,都是將指數(shù)部分轉(zhuǎn)換為二進(jìn)制進(jìn)行處理。但需要注意的是對(duì)于矩陣乘法而言,其乘法的單位元是單位矩陣。這里給出基于Groovy的矩陣快速冪實(shí)現(xiàn)。借助于Groovy的運(yùn)算符重載特性,可以很方便的進(jìn)行矩陣乘法運(yùn)算

        class?Matrix?{
        ????/**
        ?????*?矩陣階數(shù)
        ?????*/

        ????int?n

        ????/**
        ?????*?矩陣數(shù)據(jù)
        ?????*/

        ????List>?mat

        ????Matrix(List>?initValue)?{
        ????????this.n?=?initValue.size()
        ????????//?初始化矩陣數(shù)據(jù)
        ????????this.mat?=?initValue
        ????}

        ????/**
        ?????*?重載?*?乘法運(yùn)算符,?實(shí)現(xiàn)矩陣乘法
        ?????*?@param?other
        ?????*?@return
        ?????*/

        ????Matrix?multiply(Matrix?other)?{
        ????????List>?resultData?=?[]
        ????????for(?row?in?0..????????????List?rowList?=?[]
        ????????????for(?col?in?0..????????????????def?num?=?0l
        ????????????????(0..
        ????????????????????num?+=?this.mat[row][i]?*?other.mat[i][col]
        ????????????????}
        ????????????????rowList?<????????????}
        ????????????resultData?<????????}
        ????????return?new?Matrix(resultData)
        ????}

        ????/**
        ?????*?獲取n階單位矩陣
        ?????*?@param?n?階數(shù)
        ?????*?@return
        ?????*/

        ????static?Matrix?identityMat(int?n)?{
        ????????List>?resultData?=?new?ArrayList<>(n)
        ????????(0..
        ????????????List?subList?=?new?ArrayList<>(?Collections.nCopies(n,0l)?)
        ????????????subList[i]?=?1l
        ????????????resultData?<????????}
        ????????return?new?Matrix(resultData)
        ????}

        ????/**
        ?????*?矩陣快速冪
        ?????*?@param?matrix?n階方陣
        ?????*?@param?exp?指數(shù)
        ?????*?@return
        ?????*/

        ????static?Matrix?quickMatrixPower(Matrix?matrix,?long?exp)?{
        ????????//?矩陣乘法單位元:?n階單位矩陣
        ????????Matrix?result?=?Matrix.identityMat(?matrix.n?)
        ????????Matrix?temp?=?matrix
        ????????while?(exp!=0)?{
        ????????????//?取出指數(shù)在二進(jìn)制下的最后一位
        ????????????long?lastBit?=?exp&1
        ????????????//?該位不為0,?說(shuō)明最終計(jì)算結(jié)果需要乘上這個(gè)中間乘數(shù)
        ????????????if(?lastBit!=0?)?{
        ????????????????result?=?result?*?temp
        ????????????}
        ????????????//?更新中間乘數(shù)
        ????????????temp?=?temp?*?temp
        ????????????//?移除指數(shù)在二進(jìn)制下的最后一位
        ????????????exp?>>=?1
        ????????}
        ????????return?result
        ????}
        }


        瀏覽 129
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲中文字幕第一页 | 情侣战斗前必看的十部电影 | 中文字幕一区在线播放 | 国产91对白刺激露脸在线观看 | 黑屌视频| 亚洲AV无码秘 翔田 | 日本无码做爱视频 | 日本成人一线高清无码在线观看 | 在线亚洲日本 | 亚洲人成77777 |