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大数相加相乘内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-10-16

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)

深入分析C++中两个大数相乘结果不正确的问题

在编写代码做测试时发现两个大数相乘结果不正确的问题,测试代码如下: #include "stdafx.h"#include<stdlib.h>#include<time.h>int _tmain(int argc, _TCHAR* argv[]){      time_t temp1=1345172428000000;    time_t temp2=1345172428*1000000;   ::system("pause");    re

python里大整数相乘相关技巧指南

问题 大整数相乘 思路说明 对于大整数计算,一般都要用某种方法转化,否则会溢出.但是python无此担忧了. Python支持"无限精度"的整数,一般情况下不用考虑整数溢出的问题,而且Python Int类型与任意精度的Long整数类可以无缝转换,超过Int 范围的情况都将转换成Long类型. 例如: >>> 2899887676637907866*1788778992788348277389943 5187258157415700236034169791337062

js保留两位小数方法总结

本文是小编针对js保留两位小数这个大家经常遇到的经典问题整理了在各种情况下的函数写法以及遇到问题的分析,以下是全部内容: 一.我们首先从经典的"四舍五入"算法讲起 1.四舍五入的情况 var num =2.446242342; num = num.toFixed(2); // 输出结果为 2.45 2.不四舍五入 第一种,先把小数边整数: Math.floor(15.7784514000 * 100) / 100 // 输出结果为 15.77 第二种,当作字符串,使用正则匹配: Num

java编程实现两个大数相加代码示例

通常情况,实现大数运算是通过BigInteger和BigDecimal两种方法.这两种方法分别表示不可变的任意精度的整数和不可变的有符号的任意精度的十进制数(浮点数).主要用于高精度计算中.这两个类使得java中的大数,高精度运算变得很简单.但本文介绍的并不是通过上述两种方法实现Java中的大数运算. 主要的思想是:把两个数存在String中了,然后将每个数字取出,放到数组,由最末位开始计算,算加法,判断是否进位,进位则前位+1,若超过长度,则copy到新的数组. 代码如下: public cl

JS判断两个对象内容是否相等的方法示例

本文实例讲述了JS判断两个对象内容是否相等的方法.分享给大家供大家参考,具体如下: 我们知道,如果两个对象即使内容,JavaScript也会判断它们不相等.但是有时候,我们仅仅需要判断两个对象的内容是否相等.那么我们应该如何做到且考虑周全呢?比如说0和-0,null和undefined,是不相等的,NaN和NaN默认是不相等的.我写了一个isEqual方法,考虑到了诸多方面,代码如下: <!DOCTYPE html> <html> <head> <meta cha

在页面中引入js的两种方法(推荐)

在页面中引入js有两种基本方式:在页面中嵌入js.引用外部js文件. 一.在页面中嵌入js 这是在页面使用js最简单的方式了,一般我在写个小测试的情况下会用这种方式. 把script元素写在</body>前面,script元素的内容就是js代码.像这样: <script> // 在这里写js function test(){ alert('说点什么呢'); } test(); </script> 二.引用外部js文件 引用外部js文件,可以使js文件和HTML文件相分离

JS保留两位小数 四舍五入函数的小例子

js 四舍五入函数 toFixed(),里面的参数 就是保留小数的位数. 复制代码 代码如下: <script language="javascript"> document.write("<h1>JS保留两位小数例子</h1><br>");  var a=2.1512131231231321;    document.write("原来的值:"+a+"<br>");

JS比较两个数值的大小实例

一般情况下: if(2 > 10) { alert("不正确!"); } 此比较不会是想要的结果:它相当于2 >1,把10的第一位取出来比较. 解决方法: if(eval(2) > eval(10)) { alert("不正确!"); } eval()函数用于在不引用任何特定对象的情况下计算代码字符串. <script> function check() { var num1=document.form1.num1.value; var

js中小数向上取整数,向下取整数,四舍五入取整数的实现(必看篇)

js中小数向上取整数,向下取整数,四舍五入取整数的实现. 1.ceil()  向上-------------ceil英文意思是:天花板-----------就是在上 2.floor() 向下-------------ceil英文意思是:地面-----------就是在下 3.round() 四舍五入-------------ceil英文意思是:大约-----------就是附近 直接看下面的例子,结果一目了然.代码下面的是对应的打印结果. Math.floor(3/4) 0 Math.floor