简体   繁体   English

在JavaScript中处理21位小数

[英]Handle 21 decimals number in JavaScript

I'm writing an input range component in JavaScript, the component works with integers to define max , min and step values. 我正在用JavaScript编写输入范围组件,该组件与整数一起使用以定义maxminstep值。

If the user provides a decimal step value, the component will use this function to get the number of decimals and transform it to an integer: 如果用户提供了十进制step值,则组件将使用此函数获取小数位数并将其转换为整数:

export function getDecimals(num) {
  const stepArr = num.toString().split('.');
  return stepArr[1] ? stepArr[1].length : 0;
}

Doing so, the component can work with integers, and when it needs to return to the user the value inserted by the user (using the range handle), it will convert the number back to a decimal number and set the decimals to the same amount provided by step with this function: 这样做,该组件可以使用整数,并且当需要将用户插入的值(使用范围句柄)返回给用户时,它将把数字转换回十进制数并将十进制数设置为相同的数量分step提供此功能:

parseFloat(
  newValue.toFixed(getDecimals(this.props.step))
);

this.props.step is the original step value provided by the consumer of the component. this.props.step是组件使用者提供的原始step值。

It works pretty well, but I received a bug report where one of the consumers receives a RangeError because the provided step number is: 它工作得很好,但是我收到一个错误报告,其中一个使用者收到了RangeError因为提供的step号是:

0.000020735346383538284

This number has 21 decimal digits, while Number.toFixed supports no more than 20 decimal digits. 该数字具有21个十进制数字,而Number.toFixed支持不超过20个十进制数字。

Here's a repro: 这是一个复制品:

 const step = 0.000020735346383538284; function getDecimals(num) { const stepArr = num.toString().split('.'); return stepArr[1] ? stepArr[1].length : 0; } function toSafe(num) { return parseFloat(num.toFixed(getDecimals(step))); } console.log(toSafe(10)); 

I could easily fix this with: 我可以使用以下方法轻松解决此问题:

export function getDecimals(num) {
  const stepArr = num.toString().split('.');
  return Math.min(20, stepArr[1] ? stepArr[1].length : 0);
}

But in this case I'd lose the precision required by the step value, because I would never return a value with more than 20 decimal digits. 但是在这种情况下,我将失去step值所需的精度,因为我永远不会返回超过20个十进制数字的值。

How could I handle this case to preserve the precision? 如何处理这种情况以保持精度?

update : 更新

Would this function work or is it going to mess up some numbers because of the string manipulation? 此功能将起作用还是由于字符串操作而使一些数字混乱?

export function toFixed(num, decimals) {
  const parts = num.toString().split('.');
  return Number(`${parts[0]}.${(parts[1] || '').slice(0, decimals)}`);
}

A quick guess would be to use some sort of big number library. 一个快速的猜测是使用某种大数字库。 Something like this ? 这样吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM