找到数字“四舍五入到最接近的 X”的值 X

Find the value X where the number has been "rounded to the nearest X"

提问人:Party Ark 提问时间:4/19/2023 最后编辑:Party Ark 更新时间:4/20/2023 访问量:65

问:

估计最接近的四舍五入的最简单方法是什么,我们知道四舍五入总是例如 100、10、1、0.1 等。我们不一定知道原始数字。

8        => 1         // we have rounded to the nearest *one*
88       => 1
80       => 10        // we have rounded to the nearest *ten* 
4530     => 10
4000     => 1000      // we have rounded to the nearest *thousand*
0.024    => 0.001
0.02     => 0.01
0.024332 => 0.000001
4000.7   => 0.1       // we have rounded to the nearest *tenth*

当给定一个数字时,当我们想将所有其他数字四舍五入相同的数量时,这可能很有用。谢谢。

我试图确定任何数字,如果我们假设数字已经四舍五入,我们如何估计四舍五入的金额是多少?

例如,给定数字 4000,我们估计我们开始的数字四舍五入到最接近的千位。但考虑到 4000.7,我们估计四舍五入到最接近的十分之一。

JavaScript 数学 舍入 精度

评论

2赞 Raymond Chen 4/19/2023
JavaScript 浮点数不准确。在解决此问题之前,您必须使用一些其他数字表示形式。(例如,值 0.1 不作为 IEEE 浮点值存在。你可以非常接近,但它不会完全是 0.1。
0赞 derpirscher 4/19/2023
我不明白你“四舍五入”的逻辑?为什么 8 或 88 会四舍五入为 1 而不是 10 或 100?为什么 4530 会四舍五入到 10,而 4000 会四舍五入到 1000?
1赞 Raymond Chen 4/19/2023
@derpirscher 目标是找到数字“四舍五入到最接近的 X”的值 X。

答:

0赞 Ben Stephens 4/19/2023 #1

这可能有点杂乱无章,但这个想法基本上是找到第一个不为零的东西从右边开始,并基于此返回一个数字。

const get_last_non_zero_position = (num_str) => {
  let i = num_str.length - 1;
  
  for(; i >= 0; i--)
    if(num_str[i] !== '0')
      return i;
  
  return -1;
};

const get_rounding = (number) => {
  const [int_part, dec_part] = (number + '').split('.');
  
  if(dec_part?.length) {
    const dec_sig_digit = get_last_non_zero_position(dec_part);
    if(dec_sig_digit > -1)
      return '0.' + '0'.repeat(dec_sig_digit) + '1';
  }
  
  const int_sig_digit = get_last_non_zero_position(int_part);
  
  return '1' + '0'.repeat(int_part.length - int_sig_digit - 1);
};

const test_items = [
  8, 88, 80, 4530, 4000, 0.024, 0.02, 0.024332, 4000.7,
  0.1, 0.3, 0.2 + 0.1, new Decimal(0.2).plus(0.1)
];

console.log(test_items.map(
  (item) => [item, get_rounding(item)].join(': ')
));
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/9.0.0/decimal.min.js"></script>

0赞 Party Ark 4/19/2023 #2

Raymond Chen说得对——你不能用数学的方式做到这一点,因为浮点表示存在问题。因此,您需要一个基于字符串的函数。

对于整数,我们可以使用正则表达式来计算尾随零 n 的数量,四舍五入将为 10^n。

对于非整数,我们需要小数点后的数字 n 个数,这也是我们可以用正则表达式做的事情。四舍五入将是 10^n 的倒数。

function getRounding(n){
  
    const s = n.toString();
  
    if(Number.isInteger(n)){        
      return Math.pow(10, /0+$/.exec(s)?.[0].length ?? 0);      
    }
    else
    {     
      return 1/Math.pow(10, (/\.\d+/.exec(s)?.[0].length ?? 0) - 1);     
    }
  
}

console.log(getRounding(8))
console.log(getRounding(88))
console.log(getRounding(80))
console.log(getRounding(4530))
console.log(getRounding(4000))
console.log(getRounding(0.024))
console.log(getRounding(0.02))
console.log(getRounding(0.024332))
console.log(getRounding(4000.7))