[英]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: 我想出了两种方法来解决这个问题:
position = value % interval || interval
position = value % interval || interval
(relying on the falsey 0) position = value % interval || interval
(依赖于false 0) 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.