简体   繁体   English

Javascript:在余数为0时产生除数的实现模数

[英]Javascript: Implementing modulus where remainder 0 yields divisor instead

In my current project, I've often needed to know the position of a number within a given interval (and it needed to be 1-based, not 0 based). 在我当前的项目中,我经常需要知道给定时间间隔内数字的位置(并且它必须基于1,而不是基于0)。 Let's use converting time as an example -- going from the 0-based 24 hour clock to the 1-based 12 hour clock (so 12 is the interval). 让我们以转换时间为例-从基于0的24小时制转换为基于1的12小时制(因此间隔为12)。 Given 2 hrs or 14 hrs, the 'position' should be 2. Given 0 or 12, the position equals 12 (not 0). 给定2小时或14小时,“位置”应为2。给定0或12,位置等于12(而不是0)。

The obvious method is modulo -- 14 % 12 = 2 as expected. 最明显的方法是取模-如预期的那样14 % 12 = 2 However, 12 % 12 = 0 , and like I said, it needs to be 1-based. 但是, 12 % 12 = 0 ,就像我说的那样,它必须基于1。 I couldn't just add 1 to the result of the modulo to make it 1-based, because then the position of 12 in the interval 12 would be 1, the position of 14 in 12 would be 3, and so on. 我不能只将1的取模结果加1,因为在间隔12中12的位置将为1,在12中14的位置将为3,依此类推。

I came up with 2 methods to solve this: 我想出了两种方法来解决这个问题:

  1. position = value % interval || interval position = value % interval || interval (relying on the falsey 0) position = value % interval || interval (依赖于false 0)
  2. position = (value - 1) % interval + 1 (or if you need to support values that start at 0, like in the 24-hour clock, it would be (value + interval - 1) instead) position = (value - 1) % interval + 1 (或者,如果您需要支持从0开始的值,例如24小时制,则应该是(value + interval - 1)

Which of these methods should be used? 应使用以下哪种方法?
Are there pros / cons / potential pitfalls I should be aware of? 我应该注意哪些优点/缺点/潜在的陷阱?
Or is there a better method that I'm unaware of? 还是有我不知道的更好的方法?

So based on the comments I received, both methods I originally came up with were lacking in type checking and in how they handled zeros or negatives. 因此,根据我收到的评论,我最初想到的两种方法都缺乏类型检查以及它们如何处理零或负数。 Based on that feedback, I changed my function to the following: 基于该反馈,我将功能更改为以下内容:

function positionInInterval( value, interval ) {

    // Check for valid input
    // Rather than throw an error, you could return undefined or NaN
    if ( typeof value !== 'number' || typeof interval !== 'number' )
        throw new TypeError('Argument type must be Number');
    if ( interval < 2 )
        throw new RangeError('Interval must be greater than 1');

    if ( value < 0 )
        return value % interval + interval;

    return value % interval || interval;
}

It treats all numbers as being on a continuous 'number line', including negative numbers, so that by increasing value by 1, its 'position' in interval always increases by 1, until the next interval. 它将所有数字都视为连续的“数字行”,包括负数,因此通过将value增加1,其在interval “位置”始终会增加1,直到下一个间隔。


Note: user Slai indicated that || 注意:用户Slai表示|| might make Method 1 slightly slower than Method 2, but at least in Chrome, they seemed neck and neck, except when I determined value with Math.random() , in which case || 可能会使方法1的速度略慢于方法2的速度,但至少在Chrome中,它们似乎并驾齐驱, 除非我用Math.random()确定value否则 || was always slightly faster. 总是稍微快一点。


I know the use cases related to this question are limited, but I hope it helps someone out! 我知道与此问题相关的用例有限,但我希望它可以帮助某人! This is the sort of information that I never know I need until I stumble across it. 直到偶然发现这些信息,我才知道我不需要它。 :) :)

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

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