保留有效数字不会?没关系,手把手写一个

362 阅读2分钟

在平常得开发里,有时候会遇到让保留有效数字,比方说

  1. 若数值 >=10,则去尾保留 3 位小数,结果去掉小数末尾的 0。

    • 10.12345去尾保留3位小数,结果为10.123。
    • 10.00000去尾保留3位小数,并去掉小数末尾的0,结果为10。
  2. 若数值 <10 ,则去尾保留 5 位有效数字,结果去掉小数末尾的 0。

    • 0.0000012345678去尾保留5位有效数字,结果为0.0000012345。
    • 0.0000012去尾保留5位有效数字,并去掉小数末尾的0,结果为0.0000012。
    • 0.100===>0.1
    • 0.00100===>0.001
    • 9.0001234===>9.0001。
    • 9.0120003===>9.012。
    • 9.00001==>9

话不多说,直接开干

 function significantDigits(val) {
     if (!val) {
         return val
     }
     let valArr = (val + '').split('.');
     console.log('valArr', valArr);
     if (valArr.length === 1) {
         // 整数直接返回
         return val
     }
     let res = '';
     if (val >= 10) {
         // 数值>=10,去尾保留3位小数,结果去掉小数末尾的0
         this.getThree(valArr[1], 3) ? res = valArr[0] + '.' + this.getThree(valArr[1], 3) : res = valArr[0];
         console.log('res', res);
         return res
     }

     console.log('valArr[0]', valArr[0]);
     // 若数值<10,则去尾保留5位有效数字,结果去掉小数末尾的0。
     // 注意:前面的整数也要计算位数 但如果是大于等于1的 那整数位没有0  小于1 得话  整数位就也是0  
     if (valArr[0] >= 1) {
         // 整数位大于等于1 整数要计入位数 后面只要4位了
         this.getThree(valArr[1], 4) ? res = valArr[0] + '.' + this.getThree(valArr[1], 4) : res = valArr[0];
         console.log('res', res);
         return res
     }
     if (valArr[0] < 1) {
         //  整数位小于1  那就是0开头 整数不计入位数  从第一个不是0的数字开始算
         res = valArr[0] + '.' + this.findNum(valArr[1], 5);
         console.log('res', res);
         return res
     }



 }

 // 处理的的大于等于1的  这种是第一位已经确定了 只需要在小数点后面搞固定位数即可
 function getThree(val, num) {
     // 先截取num个小数,并且去掉尾巴为0的
     let arr = [];
     // 有没有需要的位数那么多个 有的话直接截取  没有 就直接源数据去尾返回即可
     val.length <= num ? (arr = val.split('')) : (arr = val.slice(0, num).split(''));
     console.log('arr', arr);
     while (arr[arr.length - 1] == 0) {
         arr.pop()
     }
     // 注意 这儿有全部为0的情况 这样arr就是空数组 所以上面的res赋值需要判断一下
     return arr.join('')
 }

// 处理 0.xxx这种得小数 这种是第一位从哪儿开始算都还没确定 得先确定位,然后再处理后面的数字
 function findNum(val, num) {   
     let result = ''
     if (val) {
         let arr = val.split('');
         let newArr = [];
         let i = 0;
         while (arr[i] == 0) {
             // 先把0搞进去
             newArr.push(arr[i])
             i++
         }
         // 这儿已经确定了第一位了  从这儿开始再往后num个就行
         let index = i + num;
         while (i < index) {
             // 有效数字搞进去
             newArr.push(arr[i])
             i++
         }
         // 不够位数就push空进去了 所以这儿需要处理一下
         newArr = newArr.filter(i => i); 
         console.log('newArr', newArr);
         // 去尾
         while (newArr[newArr.length - 1] == 0) {
             newArr.pop()
         }
         console.log('newArr1', newArr);
         result = newArr.join('')
     }
     return result
 }


 // significantDigits(10.12345)  10.123
 // significantDigits(10.00000)  10
 // significantDigits(10.001)  10.001
 // significantDigits(10.010)  10.01
 // significantDigits(9.00001)  9.00001
 // significantDigits(9.0001234 )  9.0001
 // significantDigits(9.0120003)  9.012
 // significantDigits(0.0000012345678)  0.0000012345
 // significantDigits(0.0000012)  0.0000012
 // significantDigits(0.10001)  0.10001
 // significantDigits(0.100)  0.1
 // significantDigits(0.00100)  0.001

思路就是先做大的区分

  • 大于等于10的这种整数位是确定的,直接保留3位小数去尾即可
  • 小于10的就有两种情况
    • 一种是大于等于1的,这种整数位也是确定的,直接截取4位小数,然后去尾即可
    • 另外一种是小于1的,这种第一位有效数字就需要去确定,得挨个挨个去找,知道找到那个不为0得开始,再往后去截取、去尾即可

但是有时候事情往往不是这么简单,有时候拿到的数字是科学计数法。。。

//  科学计数转化为小数 
function myToFixed(inputNumber) {
      if (isNaN(inputNumber)) {
        return inputNumber
      }
      inputNumber = '' + inputNumber
      inputNumber = parseFloat(inputNumber)
      let eformat = inputNumber.toExponential() // 转换为标准的科学计数法形式(字符串)
      let tmpArray = eformat.match(/\d(?:\.(\d*))?e([+-]\d+)/) // 分离出小数值和指数值
      let number = inputNumber.toFixed(Math.max(0, (tmpArray[1] || '').length - tmpArray[2]))
      return number
}