js实现小数点四舍五入

其实这个问题,在之前的面试中被提问到了,由于笔者平时都是用原生的toFixed()的方法来保留小数点,所以当时并没有回答出来这个问题,呜呜呜.
现在突然想起了这个问题,就研究一下吧。

最简单的实现方法

可以使用Math对象的一些方法来实现,这个比较简单,主要用到了Math.round和一些简单的乘除法运算。例子
思路:
1. 先把数值转成只有一位小数点的数值
2. 利用Math.round方法四舍五入(关键)
3. 最后通过乘除法运算等到想要的小数点位数


function toFixed(num,decimal){
if(isNaN(num)){
return 0;
}
num = num-0;
var p1 = Math.pow(10, decimal + 1);
var p2 = Math.pow(10, decimal);
console.log(num * p1 / 10);
console.log(Math.round(num * p1 / 10));
return (Math.round(num * p1 / 10) / p2).toFixed(decimal); //思考一下,为什么要除10?
}

运行一下上面的代码,其实有隐藏的bug...


toFixed(2.555,2) //2.56 toFixed(4100.065,2) //4100.06 ??? console.log(4100065/10) //410006.49999999994 这就是bug的答案 0.1+0.2=? //0.30000000000000004

所谓的隐藏bug,就是js编程语言的小数点精度问题,所以上面那个除于10 只是在一定的范围内有效,过了这个范围,还是会出现精度问题...

用字符串处理

既然小数点进行运算会出现问题,那我们换一种思路,用字符串来处理。例子
思路:
1. 把数字转成字符串,然后把小数点移动到倒数第二位。(模拟只有一位小数点)
2. 还是用到Math.round来四舍五入
3. 重复第一个步骤,不过把小数点移动到(你要保留多少位小数点)


function toFixed(num,decimal){
if(isNaN(num)){
return 0;
}
var strnum = num+'';
var arr = strnum.split('.');
if(arr.length<2){
return num.toFixed(decimal);
} strnum = arr.join(''); var strnum2 = strnum.slice(0,-1)+'.'+strnum.slice(-1); var result = Math.round(strnum2-0)+''; if(arr[1].length==decimal){
result+='0'; //如果小数点的个数刚好等于要保留的小数点个数,要补0
} return result.slice(0,-decimal)+'.'+result.slice(-decimal)
}

2020-04 更新

上面的字符串处理不够好,下面补充个新的逻辑方式:

  1. 把数字转成字符,并记录.小数点的位置;如果没有小数点,则直接在后面补0;
  2. 通过小数点的位置,计算出原数字有多少位小数(oldPointNum);把小数点去掉并且把字符串转成数组;
  3. 通过比较oldPointNum和n(要保留的位数);如果oldPointNum<n,直接补0;否则下一步
  4. 比较数组倒数(i =oldPointNum-n)的数字是否>=5;是则进一位;i++;循环该步骤(核心),用这一步来模拟四舍五入。

const toFixed = (number, n) => {
let numberStr = number + "";
let reg = /^(-|\+)?(\d+(\.\d*)?|\.\d+)$/i;
if(!reg.test(numberStr)) {
console.error('输入的数字格式不对');
return;
}
let sign = numberStr.charAt(0) === '-' ? (numberStr=numberStr.slice(1),-1):1; // 判断是否是负数
let pointIndex = numberStr.indexOf("."); // 记录小数点的位置
if (pointIndex > -1) {
numberStr = numberStr.replace(".", "");
} else { // 没有小数点直接添加补0;
numberStr += ".";
numberStr+=new Array(n).join('0');
return numberStr;
}
let numberArray = numberStr.split(""); //转成数组
let len = numberArray.length;
let oldPointNum = len - pointIndex; // 获取原数据有多少位小数
if (oldPointNum < n) { // 要保留的小数点比原来的要大,直接补0
while (n - oldPointNum > 0) {
numberArray.push(0);
n--;
}
} else if (oldPointNum > n) { // 模拟四舍五入 let i = oldPointNum - n; // 从倒数第i个数字开始比较
let more = numberArray[len - i] >= 5 ? true : false;
while (more) {
i++;
more = +numberArray[len - i] + 1 === 10 ? true : false; // 进位后判断是否等于10,是则继续进位
numberArray[len - i] = more&&i!==(len+1) ? 0 : +numberArray[len - i] + 1; // 其他位置的数字进位直接变成0,第一位的例外
console.log(i, len);
}
numberArray.length = len- (oldPointNum-n); // 截取多余的小数
}
numberArray.splice(pointIndex, 0, ".");
return sign===-1?'-'+numberArray.join(""):numberArray.join("");
};

ps :上面的代码有点臃肿,其实可以通过正则来简化,以后有空修改。

js实现小数点四舍五入的更多相关文章

  1. JS保留小数点(四舍五入、四舍六入)实例

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  2. js 让小数四舍五入保留两位小数的函数是?

    js 让小数四舍五入保留两位小数的函数是? 例子:data.relations[i].data[j].toFixed(2) toFixed(2)这个函数就是保留两位小数的作用

  3. java四舍五入BigDecimal和js保留小数点两位

    java四舍五入BigDecimal保留两位小数的实现方法: // 四舍五入保留两位小数System.out.println("四舍五入取整:(3.856)="      + ne ...

  4. js判断小数点几位

    js如何判断小数点后有几位 <script> var n=3.143423423;alert(n.toString().split(".")[1].length); & ...

  5. js保留小数点后面几位的方法

    原文地址: http://www.jb51.net/article/45884.htm 四舍五入以下处理结果会四舍五入: ? 1 2 var num =2.446242342; num = num.t ...

  6. js 获取小数点位数方法及 字符串与数字之间相互转换方法

    1.获取小数点位数方法 a. 使用 js 中 subsrting,indexOf,parseFloat三个函数,代码如下: var s = "22.127456" ;//s 为 字 ...

  7. js 小数[非]四舍五入

    1.四舍五入 (2.678).toFixed(2) // 2.68 2.不需要四舍五入 (parseInt(2.678*100)/100.0).toFixed(2) // 2.67 3.字节单位转换 ...

  8. js数字格式化-四舍五入精简版

    搜索网上的,数字格式化过余复杂,自己想了个简单方法,欢迎吐槽. 简化说明: '123333' => 12.3万 parseInt('123333') 字符串转整型 parseInt('12333 ...

  9. js 加减乘除以及四舍五入 新写法

    1 四舍五入 eg: (1.23).round() = 1.2 (1.2456).round(3) = 1.246 Number.prototype.round = function (count) ...

随机推荐

  1. Codeforces 414A

    题目链接 首先考虑无解的情况: n / 2 > k 或者 n==1 且 k != 0 (因为两个数的最大公约数最小为1) 然后因为有 n / 2 组(把 a[i] 和 a[i+1] 看成一组), ...

  2. 帮助你构建云服务的开源平台:openstack

    from:http://os.51cto.com/art/201205/336386_all.htm 概念架构 3-5 OpenStack Compute服务架构 点评:从openstack的能力来看 ...

  3. oracle控制何时触发审计动作

    1)By session / By Access by session对每个session中发生的重复操作只记录一次 by access对每个session中发生的每次操作都记录,而不管是否重复. 对 ...

  4. pl/sql基础知识—过程快速入门

    n  过程 过程用于执行特定的操作,当建立过程时,既可以指定输入参数(in),也可以指定输出参数(out),通过在过程中使用输入参数,可以将数据传递到执行部分:通过使用输出参数可以将执行部分的数据传递 ...

  5. phpmyadmin误删表后的恢复过程

    转自:http://blog.csdn.net/ssrc0604hx/article/details/18717983 话说今天不知道是抽风了还是失魂了,在用phpmyadmin删除测试数据时,竟然将 ...

  6. UIView 判断是否visible

    if(self.view == [(MyAppDelegate *)[[UIApplication sharedApplication] delegate].window.subviews objec ...

  7. php上传文件与图片到七牛的实例详解

    上传文件到七牛最简单的方式就是使用七牛官方最新的SDK 用composer安装PHP SDK composer require qiniu/php-sdk 上传文件到七牛 use Qiniu\Auth ...

  8. pictures

  9. iOS学习--详解UIView的 contentStretch属性

    通过实例和图片理解UIView的contentStretch属性 方法 通过一个图片建立一个简单的UIImageView 设置它的contentStretch属性 修改它的frame属性 观察 测试用 ...

  10. python基础之逻辑题(2)

    python基础之逻辑题(2) 1.若k为整数,下列while循环执行的次数为? 2.请输出正确结果-----numbers? 3.求结果-----math?   4.求结果-----sum? 5.输 ...