【问题标题】:Round number up to the nearest multiple of 3将数字四舍五入到最接近的 3 的倍数
【发布时间】:2011-03-16 07:20:48
【问题描述】:

嘿,我将如何将一个数字四舍五入到最接近 3 的倍数?

即

25 would return 27
1 would return 3
0 would return 3
6 would return 6

谢谢

【问题讨论】:

标签: javascript integer rounding


【解决方案1】:
    if(n > 0)
        return Math.ceil(n/3.0) * 3;
    else if( n < 0)
        return Math.floor(n/3.0) * 3;
    else
        return 3;

【讨论】:

  • 不认为这会起作用,只会带回相同的数字
  • 这是为什么呢?假设我们有 7,我们想要 9, 7/3=2.33333, ceil(2.3333)=3, 3*3=9。我错过了什么吗?
  • Cambium 是正确的 - 它有效,因为它在再次乘以 3 之前将 n/3 向上舍入到最接近的整数。
  • 看起来要求是错误的,但这不一定由开发人员决定。给客户他们想要的东西,然后通过鼻子向他们收取后续更改的费用;)
  • @PaulJWilliams:但由于客户的要求与问题陈述不一致,唯一可能的答案是{25:27,1:3,0:3,6:6}[x]。即使您忽略x=0 的情况,如果-3 明显小于-1,如何将-1 舍入到-3?所述问题的正确答案是Math.ceil(x/3)*3。
【解决方案2】:

(n - n mod 3)+3

【讨论】:

  • javascript 的 mod 运算符是 %,另外它会(错误地)将已经是 3 的倍数的偶数四舍五入。
【解决方案3】:

你来了!

Number.prototype.roundTo = function(num) {
    var resto = this%num;
    if (resto <= (num/2)) { 
        return this-resto;
    } else {
        return this+num-resto;
    }
}

例子:

y = 236.32;
x = y.roundTo(10);

// results in x = 240

y = 236.32;
x = y.roundTo(5);

// results in x = 235

【讨论】:

  • Number(1).roundTo(3) 返回 0。
  • @OrangeDog 这是完美的!在您的示例中,1.6 或更多应该导致 3。较小的数字将给出 0。
  • 这个问题特别说明(并举例)所有数字都应该四舍五入。
  • else语句没用
【解决方案4】:
if(x%3==0)
    return x
else
    return ((x/3|0)+1)*3

【讨论】:

  • 当 n == 0 时不满足(疯狂的)要求。
  • 这实际上是这个问题的唯一正确答案o_O
  • O_o 什么?根据JSPerf,x/3|0 与Math.floor(x/3) 相同,但慢了 27%。另外,如果x=-4,那么它输出0,这显然是不正确的,无论你如何定义舍入。
【解决方案5】:

此函数将四舍五入到您提供的任何因子的最接近的倍数。 它不会将 0 或已经是倍数的数字四舍五入。

round_up = function(x,factor){ return x - (x%factor) + (x%factor>0 && factor);}

round_up(25,3)
27
round up(1,3)
3
round_up(0,3)
0
round_up(6,3)
6

0 的行为不是您所要求的,但这种方式似乎更加一致和有用。但是,如果您确实想四舍五入,则以下函数将执行此操作:

round_up = function(x,factor){ return x - (x%factor) + ( (x%factor>0 || x==0) && factor);}

round_up(25,3)
27
round up(1,3)
3
round_up(0,3)
3
round_up(6,3)
6

【讨论】:

    【解决方案6】:

    我用伪代码回答这个问题,因为我主要使用 SystemVerilog 和 Vera (ASIC HDL) 进行编程。 % 表示模函数。

    round_number_up_to_nearest_divisor = number + ((divisor - (number % divisor)) % divisor)
    

    这在任何情况下都有效。

    数字的模计算余数,从除数中减去该余数得到下一个除数倍数所需的数字,然后“魔术”发生了。您会认为拥有单模函数就足够了,但是在数字是除数的精确倍数的情况下,它会计算一个额外的倍数。即,24 将返回 27。附加模数通过添加 0 来防止这种情况。

    【讨论】:

    • function roundUpMultiple(num,div) {return num+((div-(num%div))%div)}
    • 这会导致小于 0 但大于 -1 的数字失去意义,因此例如 n=-.1;d=3;n+(d-n%d)%d 返回 8.326672684688674e-17。此方法还可用于通过使d 为负数将数字向下(而不是向上)四舍五入为 d 的倍数,但随后会导致大于 0 但小于 1 的数字失去意义,所以d=-3;[-3,-1,-.1,0,.1,3].map(function(x){return x+(d-x%d)%d}) 返回[-3,-3,-3,0,-8.326672684688674e-17,3]。
    【解决方案7】:

    简单地说:

    3.0*Math.ceil(n/3.0)
    

    ?

    【讨论】:

    • 除了op对n = 0的要求外,这应该更高。
    • 为了符合疯狂的要求,加if (n === 0) return 3:P
    • 这会向上或向下舍入到最接近的倍数,而不是总是向上舍入,或者例如 3.0*Math.round(25/3.0) 返回 24 而不是 27。
    • 哦,是的,它应该是 Math.ceil
    • 将ceil 更改为floor,使其始终向下舍入到最接近的倍数。 ceil 到 round 以四舍五入到最接近的倍数。
    【解决方案8】:

    $(document).ready(function() {
        var modulus = 3;
        for (i=0; i < 21; i++) {
            $("#results").append("<li>" + roundUp(i, modulus) + "</li>")
        }
    });
    
    
    function roundUp(number, modulus) {
        var remainder = number % modulus;
        if (remainder == 0) {
            return number;
        } else {
            return number + modulus - remainder;
        }
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    Round up to nearest multiple of 3:
    <ul id="results">
    </ul>

    【讨论】:

      【解决方案9】:

      正如对已接受答案的评论中提到的那样,您可以使用它:

      Math.ceil(x/3)*3
      

      (即使x 为 0 时它不返回 3,因为这可能是 OP 的错误。)

      在此之前发布的九个答案中(尚未删除或分数不低以至于并非对所有用户可见),只有 Dean Nicholson 的答案(除了丢失的问题意义)和beauburrier是正确的。接受的答案给出了负数的错误结果,并为 0 添加了一个例外,以解释 OP 可能犯的错误。另外两个答案将一个数字舍入到最接近的倍数,而不是总是向上舍入,另外一个给出负数的错误结果,还有三个甚至给出正数的错误结果。

      【讨论】:

      • 使用 ceil() 的这个和另一个需要注意的一点是 Javascript 对 ceil 和非常小的十进制值的陌生性。请注意这些示例:Math.ceil(216.3/3)*3 = 219。Math.ceil(216.00000000000003/3)*3 = 219。Math.ceil(216.000000000000003/3)*3 = 216。一个额外的小数位会中断 ceil,因此您尝试获得最接近的 3 倍数。根据您的需要,您可以@ 987654327@第一。
      【解决方案10】:

      以@Makram 的方法为基础,并结合@Adam 的后续cmets,我修改了原始的Math.prototype 示例,使其在以零为中心和无偏系统中都能准确地舍入负数:

      Number.prototype.mround = function(_mult, _zero) {
      
        var bias = _zero || false;
        var base = Math.abs(this);
        var mult = Math.abs(_mult);
      
        if (bias == true) {
          base = Math.round(base / mult) * _mult;
          base = (this<0)?-base:base ;
        } else { 
          base = Math.round(this / _mult) * _mult;
        }
      
        return parseFloat(base.toFixed(_mult.precision()));
      
      }
      
      Number.prototype.precision = function() {
        if (!isFinite(this)) return 0;
        var a = this, e = 1, p = 0;
        while (Math.round(a * e) / e !== a) { a *= 10; p++; }
        return p;
      }
      

      示例: (-2).mround(3) 返回 -3;
      (0).mround(3) 返回 0;
      (2).mround(3) 返回 3;
      (25.4).mround(3) 返回 24;
      (15.12).mround(.1) 返回 15.1

      【讨论】:

        【解决方案11】:

        一个更通用的答案可能对解决更通用问题的人有所帮助:如果您想将数字四舍五入为分数的倍数,请考虑使用库。这是 GUI 中的一个有效用例,其中小数被输入到输入中,例如,您想将它们强制为 0.25、0.2、0.5 等的倍数。那么天真的方法不会让您走得太远:

        function roundToStep(value, step) {
          return Math.round(value / step) * step;
        }
        
        console.log(roundToStep(1.005, 0.01)); // 1, and should be 1.01
        

        在尝试编写自己的函数并查找 npm 包数小时后,我决定 Decimal.js 立即完成工作。它甚至有一个 toNearest 方法可以做到这一点,您可以选择是向上、向下还是更接近的值(默认值)。

        const Decimal = require("decimal.js")
        
        function roundToStep (value, step) {
          return new Decimal(value).toNearest(step).toNumber();
        }
        
        console.log(roundToStep(1.005, 0.01)); // 1.01
        

        RunKit example

        【讨论】:

          【解决方案12】:

          使用余数运算符(模数):

          (n - 1 - (n - 1) % 3) + 3
          

          【讨论】:

            猜你喜欢
            • 2011-03-25
            • 2012-03-07
            • 2021-04-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-11-02
            • 1970-01-01
            相关资源
            最近更新 更多