【问题标题】:Generating a list of evenly distributed round numbers within a range from min to max生成从 min 到 max 范围内均匀分布的整数列表
【发布时间】:2021-01-26 15:08:18
【问题描述】:

我正在尝试使用一个填充了数字的列,并使用最小值和最大值来生成一个过滤范围列表,供用户过滤表格。使用幼稚的方法最终会导致难以处理数字范围,我真的希望有可以不管最小/最大值如何工作的整数。

我在好几个地方都看到过这个问题,并且认为我迄今为止找到的最佳答案是Stuart Ainsworth's number table answer,但我希望有非常圆的步骤。

例如,如果我需要生成 0-100000 的 4 个范围,则数字将是:

0     - 25000
25000 - 50000
50000 - 75000
75000 - 100000

但是,如果我的最小值和最大值是奇数,我会很尴尬地使用范围。

示例:如果我需要生成从 -1234 到 4321 的 5 个范围,范围是:

-1234 - -123
-123  -  988
988   - 2099
2099  - 3210
3210  - 4321

我更喜欢这样的范围:

-1234 - 0          -1234 -  0          -1234 - -100
0     - 1000        0    -  1000       -100  -  1000
1000  - 2100        1000 -  2000        1000 -  2100
2100  - 3200        2000 -  3000        2100 -  3200
3200  - 4321        3000 -  4321        3200 -  4321

或类似的东西。范围的大小需要彼此接近,但更重要的是数字易于查看和使用。

【问题讨论】:

  • “算术级数”可以解决这个问题。明确地说,一个自定义函数,它接受一个值并返回你想要的值。可能需要两个函数。一个用于值的下限,一个用于上限值。如果我能让它工作,我会尽快发布解决方案
  • @GetSet,是吗?算术级数不是固定范围,而 OP 表示有兴趣对数字/范围进行模糊测试,以便产生更容易理解的最小值和最大值。
  • @SpencerD 即便如此,一些辅助函数也会有所帮助。我开始研究一个解决方案,它“参数化”了“绑定增量”,所以灵活性仍然是可能的
  • 从“希望范围喜欢”的外观来看,第一个范围 min 是最小值本身。最后一个范围的最大值是最大值本身。第二个范围的最小值和最大值约为 1,000。随后的范围约为 1,100。可以分阶段进行“算术级数”@SpencerD

标签: javascript math range sequence


【解决方案1】:

这是一种方法,它计算覆盖范围所需的最小步长,然后将其截断到最接近的 10 次方的十分之一,其中包括步长,然后返回从最小值开始到最大值结束的步长点,并带有中间边界步长距离,外边界略高以包含最小值/最大值。

const range = (min, max, steps) => {
  // minimum step size
  stepsize = (max - min) / steps;
  // increase the step size to a nice boundary
  // for example, 1/10th of the 10^n range that includes it
  pow = Math.trunc(Math.log10(stepsize)) - 1;
  stepsize = Math.trunc(stepsize / 10 ** pow) * 10 ** pow;
  // round min to the same boundary
  result = [min];
  min = Math.trunc(min / 10 ** pow) * 10 ** pow;
  for (let i = 0; i < steps - 1; i++) {
    min += stepsize;
    result.push(min);
  }
  result.push(max);
  return result;
}

console.log(range(-1234, 4321, 5));

【讨论】:

    【解决方案2】:

    尼克的方法使用“算术级数”公式。这确实是解决这个问题的唯一方法。

    以下解决方案考虑到@SpencerD 就单个算术级数如何无法获得所需结果的评论。这不是一个直接的序列,除了递增 1,100 的“中间”部分。

    因此,我发布此答案是为了证明如果分阶段分解,算术级数仍然是可能的。剩下的解释在代码cmets中。

    function lowerBound(actualValue, boundIncrement) {
        
        // lets determine the min by an arithmetic progression formula
        
        return Math.floor( actualValue / boundIncrement ) * boundIncrement
        
        
    }
    
    function upperBound(actualValue, boundIncrement) {
        
        // lets determine the max by an arithmetic progression formula, hence the + 1 for the upper range
        
        return (Math.floor( actualValue / boundIncrement ) + 1) * boundIncrement
        
    }
    
    function getRanges(min, max) {
        let nextMin = min
    
        // now lets use the helper funcs to determine the ranges based on "would prefer ranges like" from question
    
        let ranges = [];
    
    
        // if 1st range is negative, lets make it that value up to 0
        if (min < 0) {
            ranges.push([min, 0]);
            nextMin = 0;
        }
    
    
        // 2nd range requires special condition that it be on increment of 1,000
    
        if ( max > nextMin) {
    
            
            // so lets do this without conditions
            
            ranges.push([nextMin, upperBound(nextMin, 1000)]);
            nextMin = upperBound(nextMin, 1000);
    
        }
    
        // lets determine if there are subsequent ranges, on increment of 1,100
            
        if (nextMin < max) {
            
            while ( nextMin < max) {
                ranges.push([nextMin, upperBound(nextMin, 1100)])
                nextMin = upperBound(nextMin, 1100)
                
            }
            
        }
    
    
        // lastly, lets make (overwrite) the max range's max with the max value instead
        ranges[ ranges.length - 1][1] = max
    
        return ranges;
    
    }
    
    function test() {
    
        console.log( getRanges( parseInt(document.getElementById("min").value), parseInt(document.getElementById("max").value) ) );
    }
    Enter min: <input type="text" id="min" value="-1234">
        <br>
        Enter max: <input type="text" id="max" value="4321">
        <br>
        <button onclick="test()">Console.log()</button>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      相关资源
      最近更新 更多