<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          淺談乘法

          共 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ù)雜度為線性時(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)單很多了。其基本原理也是類似的,將其中的一個(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,然后采用乘法的分配律將其改寫加法。類似地,可以看到各加數(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)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  不用播放器的AV网站 | 波多野结衣系列在线天堂 | 人人看人人草 | 日韩一级片免费在线观看 | 青青草视频免费在线 |