skip to Main Content

What is the simplest way to estimate the nearest rounding, where we know the rounding is always e.g. 100, 10, 1, 0.1 etc. We don’t necessarily know the original number.

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*

This might be useful when, given one number, we want to round all other numbers by the same quantity. Thanks.

I am seeking to determine for any number, if we assume that the number has been rounded, how can we estimate what that rounding amount is?

For instance, given the number 4000, we estimate the number we started with was rounded to the nearest thousand. But given 4000.7, we estimate that the rounding was to the nearest tenth.

2

Answers


  1. Chosen as BEST ANSWER

    Raymond Chen has got this right - you cannot do this in a mathematical fashion, because of issues with floating point representations. So, you need a string-based function.

    For integers we can use a RegEx to count the number of trailing zeros n, and the rounding will be 10^n.

    For non-integers, we need the number of numbers n after the decimal point, again something we can do with RegEx. The rounding will be the inverse of 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))


  2. This is possibly a bit scrappy, but the idea is basically to find where the first thing that isn’t zero is from the right and return a number based on that.

    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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search