js中,小数的加减乘除

上图看效果
在这里插入图片描述
在这里插入图片描述

如果小数直接做运算,很容易发生如上图的精度丢失的情况,这个问题还是百度:
在这里插入图片描述

javascript 中同理。

为尽量降低这种精度丢失对数据的准确性的影响,做了相关的处理,函数如下:

	/**
	 * 计算小数位数的函数
	 * @param {String|Number} val 用于计算小数位数的数值
	 * 
	*/
	function getPointLength(val){
	  // 去除尾部得零得操作
	  val = Number(val);
	  if(String(val) == 'NaN'){
	    throw new Error("传入运算的参数必须是数值 - getPointLength")
	  }
	  let index = String(val).indexOf('.');
	  let pointLength = index !== -1 ? String(val).length - (index + 1) : 0;
	  return pointLength;
	}
	
	/**
	 * 处理小数的运算 -- 目前只接受两位数
	 * @param {Number|String} val1 参数1 
	 * @param {Number|String} val2 参数2 
	 * @param {String} arithmeticalMode 运算方式,加减乘除 + - * /, 默认是加法
	*/
	function dealDecimalArithmetic(val1, val2, arithmeticalMode = '+'){
	  // 校验传入的运算参数是否是数值
	  if(String(Number(val1)) == 'NaN' || String(Number(val1)) == 'NaN'){
	    throw new Error("传入运算的参数必须是数值")
	  }
	  if(arithmeticalMode == '/' && !val2){
	    throw new Error("被除数不能为空且不能为零")
	  }
	  let pointLength = 0, res = 0;
	  // 这是总的小数位数
	  pointLength = getPointLength(val1) + getPointLength(val2);
	  // 处理,按照整数进行计算
	  switch(arithmeticalMode){
	    case "+" :
	      res = Number(String(val1).replace(".",'')) + Number(String(val2).replace(".",''));
	      break;
	    case "-" :
	      res = Number(String(val1).replace(".",'')) - Number(String(val2).replace(".",''));
	      break;
	    case "*" :
	      res = Number(String(val1).replace(".",'')) * Number(String(val2).replace(".",''));
	      break;
	    case "/" :
	      res = Number((val1 / val2).toFixed(2));
	      break;
	  }
	  // 处理小数
	  if(arithmeticalMode !== '/'){
	    res = dealNumberPoint(res, pointLength);
	  }
	  // 长度超出范围,则进行抛错处理
	  if(String(res).length > 15){
	    throw new Error("精度丢失,无法进行准确运算")
	  }
	  return res;
	}
	
	/**
	 * 计算完成之后,根据计算结果与小数位置,补全小数
	 * @param {Integer} val 用于做小数补全处理的数值,必须是整数
	 * @pointLength {Integer} pointLength 两个参数总共的小数位数
	*/
	function dealNumberPoint(val, pointLength){
	  // 校验传入的处理值是否是小数。是就抛错 -- 小数位数长度在前面的处理中就应该全部做完
	  if(Number(val) % 1 !== 0){
	    throw new Error("传入运算的参数必须是整数 -- dealNumberPoint")
	  }
	  if(pointLength < 0 || Number(pointLength) % 1 !== 0){
	    throw new Error("小数位数的值要大于等于0的整数")
	  }
	  // 判断数据是正数还是负数
	  let flag = val < 0 ? true : false;
	  // 取绝对值进行运算
	  val = String(Math.abs(val));
	  // 小数位数与当前的整数的位数长度差,如果大于零就是需要补零操作
	  // 2021.11.08 修改 这里之前写成了 - val,导致了错误
	  let minusZero = pointLength - String(val).length;
	  if(minusZero >= 0){
	    for(let i = 0; i < minusZero; i++){
	      val = '0' + val;
	    }
	    // 循环完了之后加上 '0.'
	    val = '0.' + val;
	  }else{
	    if(val.length > 1){
	      let pointPosition = val.length - pointLength;
	      // 小数点的前部分
	      let start = val.slice(0,pointPosition);
	      // 小数点的后部分
	      let end = val.slice(pointPosition);
	      // 合成
	      val = start+'.'+end;
	    }
	  }
	  // 考虑正、负
	  return  flag ? -Number(val) : Number(val);
	}

由于除法容易出现除不尽的情况,于是做了保留小数的处理,最多保留两位小数。函数中增加的注释是自己的思路习惯,作为记录。

以上方法作为此次处理的记录,后续或许会继续优化这个方法
2021-12-10 更新一次 – 修复类似 0.8 * 1 计算得出 8 这样的错误

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值