Js的大整數(shù)(實際是字符串的乘法運算)踩坑記錄

以下內(nèi)容僅供學(xué)習(xí)交流,切勿用作其他用途

代碼寫得我頭皮發(fā)麻

本來寫代碼好好的本缠,用sproto傳輸網(wǎng)絡(luò)數(shù)據(jù)也都好好的胰柑,突發(fā)的出來一個64位的和服務(wù)器不一樣的整數(shù)卡睦,就想著是不是網(wǎng)絡(luò)傳輸代碼有bug了器仗,找了半天也沒發(fā)現(xiàn)問題融涣。正當(dāng)頭皮發(fā)麻的時候看到了js中的sproto轉(zhuǎn)大整數(shù)的時候,是有一個加法和乘法的青灼。才想起js的整數(shù)是有安全范圍的暴心,安全范圍里面這個數(shù)是準(zhǔn)確的,否則都是有誤差的

js的整數(shù)安全范圍參照
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger

js的整數(shù)安全范圍如下

console.log(Number.MAX_SAFE_INTEGER ) //9007199254740991
console.log(Number.MIN_SAFE_INTEGER) //-9007199254740991

可以用Number.isSafeInteger來判斷是不是安全的數(shù)字,

var t = 0xf00000020055;//這個t 是隨便的數(shù)字
console.log(Number.isSafeInteger(t)) //

解決方案

google了一下杂拨,很多文章說有BigInt,但是我的node終端卻是 ReferenceError: BigInt is not defined悯衬。于是弹沽,只好擼起袖子干檀夹。自己實現(xiàn)一個字符串代替數(shù)字的操作(這里只有加法減法和乘法,暫時沒有考慮除法->理由就是除法我用不到)


function addArray(a1,a2){
    let mlen = a1.length - a2.length;
    let arr1 = a1,arr2 = a2;
    if(mlen < 0){
        arr1 = a2,arr2 = a1;
        mlen = -mlen;
    }
    arr2.forEach((v,i) => {
        arr1[mlen+i] += v;
    });

    for(let i=arr1.length-1;i>-1;i--){
        if(arr1[i] > 9){
            if(i>0){
                arr1[i-1] += Math.floor(arr1[i]/10);
                arr1[i] %= 10;
            }else{
                arr1.unshift(Math.floor(arr1[i]/10));
                arr1[i+1] %= 10;
            }
        }
    }

    return arr1;
}

/**
 * 這里的話 a1必須比a2的策橘,因為我不想弄個負(fù)數(shù)
 * @param {*} a1 
 * @param {*} a2 
 */
function subArray(a1,a2){
    let l1=a1.length,l2 =a2.length
    for(let i=0;i<l2;i++){
        a1[l1-i-1] -= a2[l2-i-1];
    }

    for(let i=1;i<l1;i++){
        if(a1[l1-i] < 0){
            a1[l1-i] += 10;
            a1[l1-i-1] -=1;
        }
    }

    return a1;
}

/**
 * 長度必須相等呀數(shù)組
 * @param {*} arr1 
 * @param {*} arr2 
 */
function mulArray(arr1,arr2){
    let len = arr1.length;
    if(len == 1){
        let t = arr1[0] * arr2[0];
        let res = []
        while(t>9){
            res.push(t%10);
            t=Math.floor(t/10);
        }
        res.push(t);
        return res.reverse();
    }else{
        let mid = Math.floor(len/2),ti = mid*2-len;
        let x1 = arr1.slice(0,mid),x2=arr1.slice(mid,len),y1 = arr2.slice(0,mid),y2=arr2.slice(mid,len);
        
        let r1 = mulArray(x1,y1);
        let r2 = mulArray(x2,y2);
        let xx1 =x2.map((v,i)=>{return v+~~x1[i+ti]}),yy1 =y2.map((v,i)=>{return v+~~y1[i+ti]})
        let r3 = mulArray(xx1,yy1);
        subArray(r3,r2),subArray(r3,r1);


        let shiftLen = len-mid;
        Array.prototype.push.apply(r1,new Array(2*shiftLen).fill(0));
        Array.prototype.push.apply(r3,new Array(shiftLen).fill(0));
        Array.prototype.unshift.apply(r2,new Array(2*shiftLen).fill(0));
        r1 = addArray(r1,r2);
        r1 = addArray(r1,r3);

        while(r1.length > 0 && r1[0] ==0){
            r1.shift()
        }
        return r1;
    }

}


/**
 * @return 返回一個數(shù)組炸渡,arr.join("") 就是最終的結(jié)果
 * 參數(shù)不定,但是只能是由0-9構(gòu)成的字符串丽已,畢竟我用了parseInt蚌堵,不然會有NaN的
 * @param arg1,arg2,arg3,.....
 * 
 * @example
 * mulString("13","13") //return  [1,6,9]
 * mulString("14","14").join("") //return  169
 * mulString("1234","25864","33358","555664")
 * ...
 * 
 */
function mulString() {
    let mularr = Array.prototype.slice.call(arguments, 0).map(v => {
        return v.split("").map(vv => { return parseInt(vv) });
    }) || [];

    if (mularr.length > 1) {
        let m_arr = mularr[0],m_maxlen = m_arr.length,temp_len=0,temp_arr;
        for (let i = 1, c = mularr.length; i < c; i++) {
            temp_len = mularr[i].length
            if(m_maxlen < temp_len){
                temp_len = temp_len - m_maxlen;
                m_maxlen += temp_len;
                temp_arr = m_arr;
            }else{
                temp_len = m_maxlen - temp_len;
                temp_arr = mularr[i]
            }
            Array.prototype.unshift.apply(temp_arr,new Array(temp_len).fill(0));
            m_arr = mulArray(m_arr,mularr[i]);
            m_maxlen = m_arr.length;
        }
        return m_arr;
    } else {
        return mularr[0];
    }
}

/**test */
var a = mulString("15","15").join("")
console.log(a)//225
a = mulString("12225","15").join("")
console.log(a)//183375
a = mulString("1578643","15").join("")
console.log(a)//23679645

a = mulString("1513486","15123456").join("")
console.log(a)//22889138927616
a = mulString("1513486","15123456","33").join("")
console.log(a)//755341584611328
a = mulString("22889138927616","33").join("")
console.log(a)//755341584611328
a = mulString("22889138927461315413616","45648435153463133").join("")
console.log(a)//1044853374048826543153421290634702218928



代碼思路分治法,分而治之沛婴,參照算法的大數(shù)相乘

如果有問題歡迎討論溝通吼畏。

結(jié)語

希望上訴代碼對你有所幫助,如果沒有嘁灯,就當(dāng)做無事發(fā)生

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泻蚊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子丑婿,更是在濱河造成了極大的恐慌性雄,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羹奉,死亡現(xiàn)場離奇詭異秒旋,居然都是意外死亡,警方通過查閱死者的電腦和手機诀拭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門滩褥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人炫加,你說我怎么就攤上這事瑰煎。” “怎么了俗孝?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵酒甸,是天一觀的道長。 經(jīng)常有香客問我赋铝,道長插勤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任革骨,我火速辦了婚禮农尖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘良哲。我一直安慰自己盛卡,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布筑凫。 她就那樣靜靜地躺著滑沧,像睡著了一般并村。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上滓技,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天哩牍,我揣著相機與錄音,去河邊找鬼令漂。 笑死膝昆,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叠必。 我是一名探鬼主播荚孵,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼挠唆!你這毒婦竟也來了处窥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤玄组,失蹤者是張志新(化名)和其女友劉穎滔驾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俄讹,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡哆致,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了患膛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摊阀。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖踪蹬,靈堂內(nèi)的尸體忽然破棺而出胞此,到底是詐尸還是另有隱情,我是刑警寧澤跃捣,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布漱牵,位于F島的核電站,受9級特大地震影響疚漆,放射性物質(zhì)發(fā)生泄漏酣胀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一娶聘、第九天 我趴在偏房一處隱蔽的房頂上張望闻镶。 院中可真熱鬧,春花似錦丸升、人聲如沸铆农。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顿涣。三九已至波闹,卻和暖如春酝豪,著一層夾襖步出監(jiān)牢的瞬間涛碑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工孵淘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒲障,地道東北人。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓瘫证,卻偏偏與公主長得像揉阎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子背捌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容