欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript大數(shù)相加相乘的實(shí)現(xiàn)方法實(shí)例

 更新時(shí)間:2020年10月18日 15:31:36   作者:Clloz  
這篇文章主要給大家介紹了關(guān)于JavaScript大數(shù)相加相乘的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

JavaScript 中的最大安全整數(shù)是 2 ^{53} – 1 ,即 9007199254740991,當(dāng)我們進(jìn)行超出這個(gè)范圍的數(shù)值計(jì)算的時(shí)候就無法得到精確的值,而是一個(gè)近似值,比如我們計(jì)算 9007199254740991 + 10 得到的結(jié)果是 9007199254741000。本文講一下如何利用字符串在 JavaScript 中實(shí)現(xiàn)大數(shù)相加相乘。

相加

用字符串實(shí)現(xiàn)相加相乘基本思路就是按照我們?cè)诩埳线M(jìn)行豎式運(yùn)算一樣。對(duì)于加法,我們需要將兩個(gè)數(shù) num1 和 num2 上下對(duì)齊,然后從個(gè)位開始計(jì)算兩個(gè)數(shù)對(duì)應(yīng)位的和,循環(huán)到最高位,將每一次運(yùn)算的結(jié)果保存到一個(gè)數(shù)組 result 中去,最終用 Array.prototype.join() 方法還原成一個(gè)數(shù)組。

這里為了保持循環(huán)的正常進(jìn)行,我們需要保證兩個(gè)字符串位數(shù)相等,所以我們要用 String.prototpye.padStart() 方法將位數(shù)比較小的那一個(gè)字符串的前面用 '0' 補(bǔ)齊。

按位相加有個(gè)問題就是進(jìn)位如何保存,我的思路是這樣的。當(dāng)我們相加 num1[i] 和 num2[i] 的時(shí)候,得到的最多是一個(gè)兩位數(shù),它將影響 result 的兩位,即當(dāng)前的 result[0] 位置和即將 unshift 到 result 中的一位。當(dāng)前的 result[0] 位置的數(shù)就是計(jì)算 [i -1] 是得到的數(shù)的高位(即進(jìn)位),我們將我們計(jì)算的值加上進(jìn)位,得到的數(shù)在分成兩位分別放到 result 中。

所以總結(jié)一下就是我們計(jì)算 num1[i] + num2[i] 得到一個(gè)兩位數(shù),這個(gè)兩位數(shù)要先和 num1[i-1] + num2[i-1] 的結(jié)果的進(jìn)位(即 result[0] 相加,然后在分成 high 和 low 兩位,將 result[0] 的值用 low 位替換,然后將 high 位 unshift 到 result 最前面??梢詤⒖枷聢D理解。

所以我們每次計(jì)算都是確定一位和下一位的進(jìn)位。最后代碼如下:

let add = function (num1, num2) {
 if (isNaN(num1) || isNaN(num2)) return '';
 if (num1 === '0' || num2 === '0') return (num1 === '0' ? num2 : num1);

 let len = Math.max(num1.length, num2.length);
 num1 = num1.padStart(len, '0');
 num2 = num2.padStart(len, '0');

 let result = [];

 for (let i = len - 1; i >= 0; i--) {
  let sum = Number(num1[i]) + Number(num2[i]) + (result[0] || 0);
  let low = sum % 10;
  let high = Math.floor(sum / 10);

  result[0] = low;
  result.unshift(high);
 }
 return result.join('');
}

console.log(add('10', '9007199254740991')) //09007199254741001

代碼中我們加了兩個(gè)判斷,判斷兩個(gè)參數(shù)是否是合法數(shù)字格式,以及如果一個(gè)數(shù)是 '0' 則直接返回另一個(gè)數(shù)。

相乘

相乘的邏輯要比相加復(fù)雜一點(diǎn),但是總體思路還是根據(jù)豎式來實(shí)現(xiàn)算法,我畫了一張圖,我們借助圖來說明。

相乘是一個(gè)兩層循環(huán),我們要循環(huán)一個(gè)數(shù)的位,每一位再與另一個(gè)數(shù)循環(huán)的每一位相乘。我們每次相乘的結(jié)果最多是一個(gè)兩位數(shù)。但是與相加不同的是,相加的 high 每次都是 unshift 進(jìn)去即可,而相乘的高位也要與 result 的位進(jìn)行運(yùn)算。

我們來看一看相乘的規(guī)律,當(dāng)我們用 num1[i] * num2[j] 的時(shí)候,可能得到兩位數(shù),也可能得到一位數(shù),我們都統(tǒng)一算作兩位數(shù),高位沒有的就用 0 補(bǔ)齊,那么最后我們得到的結(jié)果將是一個(gè) i + j 位的數(shù)(開頭可能存在補(bǔ)齊的 0)。而我們每次計(jì)算 num1[i] * num2[j] 的結(jié)果影響到的都是 result 中的 i + j 和 i + j + 1 位。

和加法中邏輯一樣,我們將 num1[i] * num2[j] 的結(jié)果和 result[i + j + 1] 相加,得到的結(jié)果分為 low 和 high 分別存入 reslut 的 [i + j +1] 和 [i +j] 中。但是這里要注意,和加法不同,加法的高位直接存入就可以,我們這里的 high 對(duì)應(yīng)的 result[i + j] 可能已經(jīng)有值了,我們需要將已經(jīng)存在的值加上。

high 和 result[i +j] 的相加可能存在進(jìn)位怎么辦呢,看上圖中右邊的當(dāng)前 result 值中我們可以看到有些位存了不止一位數(shù),我們將 high + result[i +j] 的值直接連進(jìn)位一起保存到 result[i + j] 中。為什么能這樣做呢,因?yàn)橄麓斡?jì)算 num1[i] * num2[j - 1] 的時(shí)候(注意我們是從后往前遍歷),會(huì)把 result[i + j]和 low 相加,進(jìn)位自然能被處理,這也是這個(gè)算法比較重要的地方。

最后的代碼:

let multiply = function (num1, num2) {
  if (isNaN(num1) || isNaN(num2)) return '';
  if (num1 === '0' || num2 === '0') return '0';

  let l1 = num1.length,
    l2 = num2.length;

  let result = [];

  for (let i = l1 -1; i >= 0; i--) {
    for (let j = l2 - 1; j >= 0; j--) {
      let index1 = i + j;
      let index2 = i + j + 1;

      let product = num1[i] * num2[j] + (result[index2] || 0);
      result[index2] = product % 10;
      result[index1] = Math.floor(product / 10) + (result[index1] || 0);
    }
  }
  return result.join('').replace(/^0+/, '');
}

console.log(multiply('123', '234')) //28782

代碼中加了兩個(gè)判斷:是否是合法數(shù)字,如果有一個(gè)值為 0 則直接返回 0。注意最后要判斷得到的結(jié)果是否開頭有 0,如果有則要去掉,這里用的正則表達(dá)式。

總結(jié)

到此這篇關(guān)于JavaScript大數(shù)相加相乘的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)JavaScript大數(shù)相加相乘內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論