美文网首页让前端飞JavaScript 进阶营
由简单算法题引出的 JavaScript 精度误差问题

由简单算法题引出的 JavaScript 精度误差问题

作者: Parrotdance | 来源:发表于2019-01-03 21:14 被阅读0次

最近突然来了灵感, 想去 LeetCode 刷点算法题, 在一道初级题目上遇到了看似无法理解的错误.

题目:
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。

  • 示例 1:
    输入: [1,2,3]
    输出: [1,2,4]
    解释: 输入数组表示数字 123
  • 示例 2:
    输入: [4,3,2,1]
    输出: [4,3,2,2]
    解释: 输入数组表示数字 4321

简单思考了一下, 考的无非就是数字进位, 但也可以利用数组转数字 => 数字加一 => 数字转数组的方式来绕过进位运算. 于是有了以下 JS 代码:

/**
 * @param {number[]} digits
 * @return {number[]}
 */
var plusOne = function(digits) {
  let newNum = ((Number(digits.join('')) + 1)).toString();
  let result = [];
  for(let i = 0; i < newNum.length; i++) {
      result.push(newNum[i]);
  }
  return result;
};

提交以后在一个测试用例上出现了问题:

输入:[6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]
输出:[6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,0,0,0]
预期:[6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,4]

为什么后面几位都变成了 0 呢?
其实在 JS 中, 浮点数运算存在精度误差, 0.1 + 0.2 = 0.30000000000000004
从计算机层面讲, 误差的出现是因为其转为二进制计算后位数过长, 超出部分被截断后转为十进制, 导致出现精度误差.
而本题中后面几位都变成 0 的原因也比较类似: 简单地说, 数字大小超出了单个变量的长度限制, 存储时以类似 1.222e32 的形式存储, 仅保留了长度限制内的精度信息, 取出时长度限制以外的位则默认补 0.

其实 JS 中也内置了最大和最小安全整数值:

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

可以看出长度刚好就是错误的输出中没有补 0 的长度.

因此, 在本题中为了满足全体整数的情况, 在处理较大的数字时依然需要通过字符串的方式存储, 这样一来进位运算当然就是不可避免的了.

相关链接:
关于JS精度丢失问题
关于JS最大安全整数

相关文章

  • 由简单算法题引出的 JavaScript 精度误差问题

    最近突然来了灵感, 想去 LeetCode 刷点算法题, 在一道初级题目上遇到了看似无法理解的错误. 题目:给定一...

  • [8kyu]Find Multiples of a Number

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 任务 在这个简单的练习...

  • JS中如何理解浮点数?

    本文由云+社区发表 相信大家在平常的 JavaScript 开发中,都有遇到过浮点数运算精度误差的问题,比如 co...

  • [8kyu]How old will I be in 2099?

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 场景 Philip 刚...

  • [6kyu]FizzBuzz++

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 相关题型 [7kyu]...

  • [7kyu]Frugal Pizza

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 场景 你喜欢比萨,但是...

  • [8kyu]Welcome!

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 场景 您所在公司的广告...

  • [8kyu]Find the first non-consecu

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 任务 找到不连续的数组...

  • [8kyu]Exclamation marks series #

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 任务 删除句子中多余的...

  • [7kyu]Find twins

    该算法题来自于 codewars【语言: javascript】,翻译如有误差,敬请谅解~ 任务 找出数组中重复的...

网友评论

    本文标题:由简单算法题引出的 JavaScript 精度误差问题

    本文链接:https://www.haomeiwen.com/subject/jaoqrqtx.html