Skip to content

小数进位重写(Number.prototype.toFixed)

小数进位重写(Number.prototype.toFixed)

它是根据二进制来计算得出小数位是否进位 当二进制符合特殊条件会导致满 5不进位 比如 12345.56/.toFixed(1) = 12345.5 || 12345.54/.toFixed(1) = 12345.6

typescript

declare global {
    interface Number {
        toFixed(decimalPlaces: number): string;
    }
}


Number.prototype.toFixed = function (decimalPlaces?: number): string {
    //拿取整数值,并转换为primitive number
    const num = this.valueOf(); 
    // 检查是否为NaN或无效参数
    if (isNaN(num)) {
        //如果是无效参数直接return 'NaN'
      return 'NaN';  
    }

    // 判断传来的参数错误 默认替换成0
    if (decimalPlaces !== undefined && (isNaN(decimalPlaces) || !Number.isInteger(+decimalPlaces))) {
      decimalPlaces = 0;
    }

    const numString = `${num}`; //切换为字符串
    //1.判断是否是整数
    if (!num) {
      return typeof num === 'number' ? '0' : String(num);
    }

    //是否有值
    if (typeof num !== "number") {
      return numString;
    }

    //截取必须有值且大于0才会工作否则不工作
    if (decimalPlaces === undefined || decimalPlaces < 0) {
      return numString;
    }

    // 截取字符串 获取小数部分及整数部分
    const parts = numString.split('.');
    const num1 = parts[0];
    const num2 = parts.length > 1 ? parts[1] : '';

    //进行补0操作
    const buling = (diff?: number) => {
      let ling = '';
      // Ensure decimalPlaces is defined with a default value of 0
      const places = decimalPlaces !== undefined ? decimalPlaces : 0;
      for (let i = 0; i < (diff !== undefined ? diff : places); i++) {
        ling += '0';
      }
      return ling;
    };

    //判断是否是小数
    if (parts.length > 1) {
      //判断小数位数是否大于 用户传进来的位数 如果小于用户传进来的位数不需要操作直接补0即可
      if (num2.length <= decimalPlaces) {
        //用户传进来的小数位数 - 解构出来的小数 = 需要补0的位数
        const diff = decimalPlaces - num2.length;
        //返回补充0后的值
        return `${num1}.${num2}${buling(diff)}`;
      }

      //截取小数部分
      let num2String = num2.substring(0, decimalPlaces);
      //截取小数部分的下一个值
      const num2Next = num2.substring(decimalPlaces, decimalPlaces + 1);
      console.log("🚀 ~ num2Next:", num2Next)

      // 判断 num2Next 是否大于等于5 如果大于等于5那么需要进行简单计算
      if (Number(num2Next) >= 5) {
        //如果num2Next大于等于5则当前num2String需要进行+1操作
        const num2Num = Number(num2String) + 1;
        num2String = `${num2Num}`;
        
        //加完后检查是否进位(需要考虑位数和10的次方关系)
        if (num2Num >= Math.pow(10, decimalPlaces)) {
          // 如果小数部分进位后超过了指定小数位,说明小数部分全为0,整数部分需要+1
          const numInt = Number(num1);
          const newInt = numInt + (numInt >= 0 ? 1 : -1);
          return `${newInt}.${buling()}`;
        } else {
          // 补齐可能缺少的前导零
          if (num2String.length < decimalPlaces) {
            num2String = num2String.padStart(decimalPlaces, '0');
          }
          //否则的话可以原封不动返回
          return `${num1}.${num2String}`;
        }
      } else {
        //否则的话不需要计算直接字符串拼接在一起返回
        return `${num1}.${num2String}`;
      }
    } else {
      //不是小数补0并且直接返回
      return `${num1}.${buling()}`;
    }
}

不知道说啥了很无语了