JavaScript大数相加相乘的实现方法实例

前言

JavaScript 中的最大安全整数是 2 ^{53} – 1 ,即 9007199254740991,当我们进行超出这个范围的数值计算的时候就无法得到精确的值,而是一个近似值,比如我们计算 9007199254740991 + 10 得到的结果是 9007199254741000。本文讲一下如何利用字符串在 JavaScript 中实现大数相加相乘。

相加

用字符串实现相加相乘基本思路就是按照我们在纸上进行竖式运算一样。对于加法,我们需要将两个数 num1 和 num2 上下对齐,然后从个位开始计算两个数对应位的和,循环到最高位,将每一次运算的结果保存到一个数组 result 中去,最终用 Array.prototype.join() 方法还原成一个数组。

这里为了保持循环的正常进行,我们需要保证两个字符串位数相等,所以我们要用 String.prototpye.padStart() 方法将位数比较小的那一个字符串的前面用 '0' 补齐。

按位相加有个问题就是进位如何保存,我的思路是这样的。当我们相加 num1[i] 和 num2[i] 的时候,得到的最多是一个两位数,它将影响 result 的两位,即当前的 result[0] 位置和即将 unshift 到 result 中的一位。当前的 result[0] 位置的数就是计算 [i -1] 是得到的数的高位(即进位),我们将我们计算的值加上进位,得到的数在分成两位分别放到 result 中。

所以总结一下就是我们计算 num1[i] + num2[i] 得到一个两位数,这个两位数要先和 num1[i-1] + num2[i-1] 的结果的进位(即 result[0] 相加,然后在分成 high 和 low 两位,将 result[0] 的值用 low 位替换,然后将 high 位 unshift 到 result 最前面。可以参考下图理解。

所以我们每次计算都是确定一位和下一位的进位。最后代码如下:

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

代码中我们加了两个判断,判断两个参数是否是合法数字格式,以及如果一个数是 '0' 则直接返回另一个数。

相乘

相乘的逻辑要比相加复杂一点,但是总体思路还是根据竖式来实现算法,我画了一张图,我们借助图来说明。

相乘是一个两层循环,我们要循环一个数的位,每一位再与另一个数循环的每一位相乘。我们每次相乘的结果最多是一个两位数。但是与相加不同的是,相加的 high 每次都是 unshift 进去即可,而相乘的高位也要与 result 的位进行运算。

我们来看一看相乘的规律,当我们用 num1[i] * num2[j] 的时候,可能得到两位数,也可能得到一位数,我们都统一算作两位数,高位没有的就用 0 补齐,那么最后我们得到的结果将是一个 i + j 位的数(开头可能存在补齐的 0)。而我们每次计算 num1[i] * num2[j] 的结果影响到的都是 result 中的 i + j 和 i + j + 1 位。

和加法中逻辑一样,我们将 num1[i] * num2[j] 的结果和 result[i + j + 1] 相加,得到的结果分为 low 和 high 分别存入 reslut 的 [i + j +1] 和 [i +j] 中。但是这里要注意,和加法不同,加法的高位直接存入就可以,我们这里的 high 对应的 result[i + j] 可能已经有值了,我们需要将已经存在的值加上。

high 和 result[i +j] 的相加可能存在进位怎么办呢,看上图中右边的当前 result 值中我们可以看到有些位存了不止一位数,我们将 high + result[i +j] 的值直接连进位一起保存到 result[i + j] 中。为什么能这样做呢,因为下次计算 num1[i] * num2[j - 1] 的时候(注意我们是从后往前遍历),会把 result[i + j]和 low 相加,进位自然能被处理,这也是这个算法比较重要的地方。

最后的代码:

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

代码中加了两个判断:是否是合法数字,如果有一个值为 0 则直接返回 0。注意最后要判断得到的结果是否开头有 0,如果有则要去掉,这里用的正则表达式。

总结

到此这篇关于JavaScript大数相加相乘的实现方法的文章就介绍到这了,更多相关JavaScript大数相加相乘内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript实现大数的运算

    对于非常大或非常小的数,可以用科学记数法表示浮点值.采用科学记数法,可以把一个数表示为数字加e/E,后面加乘以10的倍数,如: 复制代码 代码如下: var num1 = 3.125e7; // 31250000 var num2 = 3e-17; // 0.00000000000000003 进行特别大的数的加减运算,可以使用字符串+科学记数法的方法来进行,如: 复制代码 代码如下: // 这里只考虑大整数的情况,不考虑小数 function strAdd(sNum1, sNum2){   /

  • JavaScript 大数据相加的问题

    同样是一道面试题,来自有道前端的面试. 写一个函数处理大数据的相加问题,所谓的大数据是指超出了整型,长整型之类的常规数据类型表示范围的数据.实现语言不限. 我是用js实现的,说一下我自己的思路: 1.首先这个题目最重要的环节在考虑怎么存储大数据?用什么数据类型保存呢?最简单可行的方式是String 2.确定了使用何种类型保存数据之后这个题目就明朗了.首先判断两个传入字符串的长度,取最短的len循环,两者从低位开始对应位相加,同时注意保存进位.在短的数据处理完后,将进位交给较长串的剩余部分处理.

  • JQery jstree 大数据量问题解决方法

    问题解决:生成的树是逐级加载的,在open函数中有一个生成节点的代码: 代码 复制代码 代码如下: for (var i=0; i<data.length; i++) { var n = TREE_OBJ.create(data[i], $(NODE)); if (onaddnode) onaddnode(n); } var firstChild = TREE_OBJ.children(NODE)[0]; if ($(firstChild).attr('id')==-1) TREE_OBJ.re

  • JS实现两个大数(整数)相乘

    大数,即超出语言所能表示的数字最大范围的数字,此时的数字只能用字符串来表示.那么如何实现两个大数相乘呢?我用JS实现了一下,代码如下: 复制代码 代码如下: console.log(bigMut("567", "1234")); // 699678 function bigMut(big, common) { big += ""; common += ""; if (big.length < common.length)

  • JavaScript大数相加相乘的实现方法实例

    前言 JavaScript 中的最大安全整数是 2 ^{53} – 1 ,即 9007199254740991,当我们进行超出这个范围的数值计算的时候就无法得到精确的值,而是一个近似值,比如我们计算 9007199254740991 + 10 得到的结果是 9007199254741000.本文讲一下如何利用字符串在 JavaScript 中实现大数相加相乘. 相加 用字符串实现相加相乘基本思路就是按照我们在纸上进行竖式运算一样.对于加法,我们需要将两个数 num1 和 num2 上下对齐,然后

  • javascript设置和获取cookie的方法实例详解

    本文实例讲述了javascript设置和获取cookie的方法.分享给大家供大家参考,具体如下: 1. 设置cookie function setCookie(cookieName,cookieValue,cookieExpires,cookiePath) { cookieValue = escape(cookieValue);//编码latin-1 if(cookieExpires=="") { var nowDate = new Date(); nowDate.setMonth(n

  • javascript设置文本框光标的方法实例小结

    本文实例总结了javascript设置文本框光标的方法.分享给大家供大家参考,具体如下: 对于text //得到光标位置 function getCaret(textbox) { var control = document.activeElement; textbox.focus(); var rang = document.selection.createRange(); rang.setEndPoint("StartToStart",textbox.createTextRange

  • JavaScript解析及序列化JSON的方法实例分析

    本文实例讲述了JavaScript解析及序列化JSON的方法.分享给大家供大家参考,具体如下: JSON 之所以这么流行,是因为 JSON 数据结构可以被解析为 JavaScript 对象.JSON 之前的 XML 数据结构要被解析,需要先解析成 DOM 文档,然后再从中提取出数据.相比之下,JSON 数据结构方便多咯O(∩_∩)O~ 所以 JSON 就成为 web 开发中,用于数据交换的事实标准. 1 JSON 对象 早期的 JSON 解析器是使用 JavaScript 的 eval() 函数

  • JavaScript函数的4种调用方法实例分析

    本文实例讲述了JavaScript函数的4种调用方法.分享给大家供大家参考,具体如下: JavaScript 函数有 4 种调用方式: 1. 作为一个函数调用 2. 函数作为方法调用 3. 使用构造函数调用函数 4. 作为函数方法调用函数 分述如下: 每种方式的不同方式在于 this 的初始化. 作为一个函数调用 function myFunction(a, b) { return a * b; } myFunction(10, 2); // myFunction(10, 2) 返回 20 以上

  • JavaScript函数内部属性和函数方法实例详解

    函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块. 函数是对象,有自己的属性和方法 .首先通过console下输出的函数属性方法来直观的看一下: 函数内部属性只要包括两个特殊的对象:arguments和this. 函数属性包括:length和prototype 函数方法(非继承)包括:apply()和call() 继承而来的函数方法:bind().toString().toLocaleString().valueOf() 其他的目前不熟,后面再补充 1. 函数内部属性 在函数内部,有两

  • Javascript中indexOf()和lastIndexOf应用方法实例

    indexOf()方法 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置. 注释:indexOf() 方法对大小写敏感! 注释:如果要检索的字符串值没有出现,则该方法返回 -1. 用之前的charAt()方法 var str ='www.webclks.com/archives/3309'; for(var i=0; i<str.length; i++){ if(str.charAt(i)==='/'){ alert(i); } } indexOf()方法 var str

  • javascript中Array数组的迭代方法实例分析

    本文实例讲述了javascript迭代的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: //filter() 利用指定的函数确定是否返回数组中包涵的某一项 var num = [1,2,3,4,5,6,12]; num.filter(function(item, index, array){ return (item > 2); //[3, 4, 5, 6, 12] }); //map() 返回一个数组,数组中每一项都是在原始数组中的对应项上运行传入参数的结果 var nu

  • Javascript setInterval的两种调用方法(实例讲解)

    如下所示: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head>    <title>&l

  • JavaScript调用后台的三种方法实例

    方法一:直接使用<%=%>调用 前台JS: 复制代码 代码如下: <script type="text/javascript">         var methodStr = "<%=BehindMethod() %>";         alert(methodStr);         </script> 后头方法: 复制代码 代码如下: public static string BehindMethod()  

随机推荐