JS大數相加

記得之前看到過一個JS超大正整數相加的題目,今天想了下自己會怎麼實現,於是便進行了嘗試,代碼如下:

function  bigAdd(a, b){
	    let  lenA = a.length,
			 lenB = b.length,
			 curry = 0,
			 res = [];
		let loopLen = Math.max(lenA, lenB );

		for(let i = 0 ; i < loopLen ; i++){
			const indexA = ( lenA - i - 1 ) > -1 ? lenA - i -1 : -1;
			const indexB = ( lenB - i - 1) > -1 ? lenB - i -1 : -1;

			const valA = indexA > -1 ? a[ indexA ] : 0 ;
			const valB = indexB > -1 ? b[ indexB ] : 0 ;

			res[i] = (  Number(valA) + Number(valB)  + curry) % 10;
			curry = Math.floor( ( Number(valA) + Number(valB)  + curry ) / 10 );
		}	
		return res.reverse().join('');
	}

想法很簡單,就是按照加法的規律,從末尾開始一項一項的相加。
然後看了網上關於該題目的算法,真是驚歎別人算法的簡潔以及對於JS中類型轉換相關知識的巧妙應用。

	function addBig(a, b){
		let temp = 0,
			res = '';
		a = a.split('');
		b = b.split('');
		while( a.lenght || b.length || temp){
			temp += ~~a.pop() + ~~b.pop();
			res = (temp % 10 ) + res;
			temp = temp > 9;
		}
		return res.replace(/^0+/g, '');
	}

首先,這個代碼給人的感覺真的很精簡。但是其中其實隱藏了很多關於JS 中類型轉換的相關知識, 下面我們來一一分析。
1.爲什麼將a,b轉換爲數組
轉換爲數組的目的是爲了在while循環體中使用 pop方法來獲取數組中的最後一項。如果你不轉換爲數組,我們能想到的獲取字符串的最後一項的方法是sutstr(-1,1)。但是這種方法只能獲取最後一項,無法動態的改變字符串本身。
2. 爲什麼while的判斷條件是 a.lenght || b.length || temp而不是a || b || temp
因爲循環體中每次的循環會使數組長度減少1,當數組爲空時,假設極端的條件下 a, b都爲[],但是這個時候 [] || [] || 0 的結果是 true, 循環永不結束。只因爲Boolean([]) = true
3. 爲什麼使用~~a.pop(),如果只是 爲了將值轉換爲數字 ,爲何不使用Number進行強制轉換不是更加易懂?
這個就十分精髓了,首先使用~操作符進行取反是會將字符串轉換爲數字的,在進行一個取反操作,就轉換爲了字符串本身代表的數字,但不僅如此。考慮下我們數組循環的最後爲空時,[].pop()的結果爲undefined, 而 Number(undefined)的結果爲NaN~NaN的結果爲-1~~NaN的結果 爲0,當你使用NaN進行加法運算時,一切結果都沒有了意義。所以這個地方必須爲~~a.pop(), 而不能使用Number進行強制轉換。
4. 爲什麼temp = temp > 9,這是什麼鬼?
這一點其實也是用了JS中的隱式轉換,我們換個寫法你就明白了temp = temp > 9 ? 1 : 0temp實際上表示的是進位的結果,在循環的開始我們使用temp += ~~a.pop() + ~~b.pop();進行temp的再賦值,實際等價於temp = (true | false) + Number。 而Boolean在進行數字運算時,true會轉換爲1,false會轉換爲0,此處巧妙的應用了該隱式轉換。

一個小小的算法,其中隱含了這麼多的基礎知識,所以還是需要夯實基礎啊!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章