如何在 JavaScript 中执行整数除法并分别获取余数
在 JavaScript 中,如何获取:
- 给定整数进入另一个整数的总次数?
- 剩下的呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
在 JavaScript 中,如何获取:
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(21)
对于某些数字
y
和某些除数x
计算商 (quotient
)[1] 和余数 (>余数
)为:示例:
[1] 一个数除以另一个数所得的整数
For some number
y
and some divisorx
compute the quotient (quotient
)[1] and remainder (remainder
) as:Example:
[1] The integer number resulting from the division of one number by another
我不是按位运算符方面的专家,但这里有另一种获取整数的方法:
这对于负数也适用,而
Math.floor()
将以错误的方向舍入。这似乎也是正确的:
注意:仅使用
~~
作为Math.trunc()
当您确信输入范围在 32 位范围内时整数。I'm no expert in bitwise operators, but here's another way to get the whole number:
This will work properly for negative numbers as well, while
Math.floor()
will round in the wrong direction.This seems correct as well:
Note: Only use
~~
as a substitution forMath.trunc()
when you are confident that the range of input falls within the range of 32-bit integers.我在 Firefox 上做了一些速度测试。
以上均基于 1000 万次试验。
结论:使用
(a/b>>0)
(或(~~(a/b))
或(a /b|0)
) 实现约 20% 的效率提升。另请记住,当a/b<0 && 时,它们都与 Math.floor 不一致。 a%b!=0
。I did some speed tests on Firefox.
The above is based on 10 million trials for each.
Conclusion: Use
(a/b>>0)
(or(~~(a/b))
or(a/b|0)
) to achieve about 20% gain in efficiency. Also keep in mind that they are all inconsistent withMath.floor
, whena/b<0 && a%b!=0
.ES6 引入了新的
Math.trunc< /code>
方法。这允许修复@MarkElliot的答案,使其也适用于负数:
请注意
数学
与按位运算符相比,方法的优势在于它们可以处理超过 231 的数字。ES6 introduces the new
Math.trunc
method. This allows to fix @MarkElliot's answer to make it work for negative numbers too:Note that
Math
methods have the advantage over bitwise operators that they work with numbers over 231.我通常使用:
它可能不是最优雅的,但它有效。
I normally use:
It's probably not the most elegant, but it works.
您可以使用函数
parseInt
来获取截断的结果。要获得余数,请使用 mod 运算符:
parseInt 对于字符串有一些陷阱,要避免使用基数为 10 的基数参数
在某些情况下,数字的字符串表示形式可能是科学记数法,在这种情况下,parseInt 将产生错误的结果。
该调用将产生 1 作为结果。
You can use the function
parseInt
to get a truncated result.To get a remainder, use mod operator:
parseInt have some pitfalls with strings, to avoid use radix parameter with base 10
In some cases the string representation of the number can be a scientific notation, in this case, parseInt will produce a wrong result.
This call will produce 1 as result.
Math.floor(operation)
返回运算的向下舍入值。第一个第问题示例:
第二个问题示例:
Math.floor(operation)
returns the rounded down value of the operation.Example of 1st question:
Example of 2nd question:
我们可以使用下面的方法。
以及我们可以通过模运算符获得提醒的任何方式
we can use the below approach.
and any way we can get reminder with modulo operator
使用:
还有一个正在研究的提案:
模数和附加整数数学
Use:
There is also a proposal working on it:
Modulus and Additional Integer Math
JavaScript 按照负数的下限和非整数的余数计算它们的数学定义。
FLOOR被定义为“小于参数的最大整数”,因此:
REMAINDER 定义为除法的“剩余部分”(欧几里得算术)。当被除数不是整数时,商通常也不是整数,即没有余数,但如果强制商为整数(这就是当有人试图获取余数或模数时会发生的情况)浮点数),显然会有一个非整数“剩余”。
JavaScript 确实会按预期计算所有内容,因此程序员必须小心提出正确的问题(人们应该小心回答所问的问题!)Yarin 的第一个问题不是“X 除以 Y 的整数除法是什么”,而是,相反,“给定整数进入另一个整数的全部次数”。对于正数,两者的答案相同,但对于负数则不同,因为整数除法(除以除数)将比一个数字(除数)“进入”另一个数字(被除数)的时间小 -1。换句话说,FLOOR 将返回负数整数除法的正确答案,但 Yarin 没有问这个!
gammax 回答正确,该代码按照 Yarin 的要求工作。另一方面,塞缪尔错了,我猜他没有做数学,否则他会发现它确实有效(而且,他没有说他的例子的除数是什么,但我希望它是3):
余数 = X % Y = -100 % 3 = -1
GoesInto = (X - 余数) / Y = (-100 - -1) / 3 = -99 / 3 = -33
顺便说一句,我测试了在 Firefox 27.0.1 上运行代码,它按预期工作,对于正数和负数以及非整数值(对于股息和除数)。示例:
-100.34 / 3.57: GoesInto = -28, Remainder = -0.3800000000000079
是的,我注意到,那里有一个精度问题,但我没有时间检查它(我不知道这是否是 Firefox 的问题) 、Windows 7 或使用我的 CPU 的 FPU)。不过,对于 Yarin 的问题(仅涉及整数),gammax 的代码运行得很好。
JavaScript calculates right the floor of negative numbers and the remainder of non-integer numbers, following the mathematical definitions for them.
FLOOR is defined as "the largest integer number smaller than the parameter", thus:
REMAINDER is defined as the "left over" of a division (Euclidean arithmetic). When the dividend is not an integer, the quotient is usually also not an integer, i.e., there is no remainder, but if the quotient is forced to be an integer (and that's what happens when someone tries to get the remainder or modulus of a floating-point number), there will be a non-integer "left over", obviously.
JavaScript does calculate everything as expected, so the programmer must be careful to ask the proper questions (and people should be careful to answer what is asked!) Yarin's first question was NOT "what is the integer division of X by Y", but, instead, "the WHOLE number of times a given integer GOES INTO another". For positive numbers, the answer is the same for both, but not for negative numbers, because the integer division (dividend by divisor) will be -1 smaller than the times a number (divisor) "goes into" another (dividend). In other words, FLOOR will return the correct answer for an integer division of a negative number, but Yarin didn't ask that!
gammax answered correctly, that code works as asked by Yarin. On the other hand, Samuel is wrong, he didn't do the maths, I guess, or he would have seen that it does work (also, he didn't say what was the divisor of his example, but I hope it was 3):
Remainder = X % Y = -100 % 3 = -1
GoesInto = (X - Remainder) / Y = (-100 - -1) / 3 = -99 / 3 = -33
By the way, I tested the code on Firefox 27.0.1, it worked as expected, with positive and negative numbers and also with non-integer values, both for dividend and divisor. Example:
-100.34 / 3.57: GoesInto = -28, Remainder = -0.3800000000000079
Yes, I noticed, there is a precision problem there, but I didn't had time to check it (I don't know if it's a problem with Firefox, Windows 7 or with my CPU's FPU). For Yarin's question, though, which only involves integers, the gammax's code works perfectly.
原始函数
div
(计算除法的商)和mod
(计算余数)有多种可能的定义 的除法)满足以下约束:Number.isInteger(div(x, y))
;x === div(x, y) * y + mod(x, y)
;Math.abs((mod(x, y))。
计算机科学文献和编程语言中常用的定义基于
截断除法,也满足
mod(x, y) * x >= 0
:地板除法,也满足满足
mod(x, y) * y >= 0
:欧几里得除法,也满足满足
mod(x, y) >= 0
:因此,
x >= 0
且>y> 0
,则截断除法、落地除法和欧几里得除法一致;0
,则截断除法和欧氏除法一致;根据论文'函数 div 和 mod 的欧几里得定义' 作者:Raymond Boute:
There are several possible definitions for the primitive functions
div
(which computes the quotient of a division) andmod
(which computes the remainder of a division) that satisfy these constraints:Number.isInteger(div(x, y))
;x === div(x, y) * y + mod(x, y)
;Math.abs((mod(x, y)) < Math.abs(y)
.The definitions that are in common usage in the computer science literature and in programming languages are based on
the truncated division, which also satisfies
mod(x, y) * x >= 0
:the floored division, which also satisfies
mod(x, y) * y >= 0
:the Euclidean division, which also satisfies
mod(x, y) >= 0
:Consequently,
x >= 0
andy > 0
, then the truncated, floored, and Euclidean divisions agree;x >= 0
andy < 0
, then the truncated and Euclidean divisions agree;x <= 0
andy > 0
, then the floored and Euclidean divisions agree;x <= 0
andy < 0
, then the truncated and floored divisions agree.The choice of the Euclidean division is recommended over the truncated and floored divisions for defining the functions
div
andmod
, according to the paper ‘The Euclidean definition of the functions div and mod’ by Raymond Boute:Alex Moore-Niemi 的评论作为答案:
对于 Rubyists,请在 Google 中搜索
divmod
,你可以这样实现它:结果:
Alex Moore-Niemi's comment as an answer:
For Rubyists here from Google in search of
divmod
, you can implement it as such:Result:
如果您需要计算非常大的整数的余数,而 JS 运行时无法这样表示(任何大于 2^32 的整数都表示为浮点数,因此会丢失精度),您需要采取一些技巧。
这对于检查我们日常生活中许多情况下出现的许多校验数字尤其重要(银行帐号,信用卡......)
首先,您需要将您的号码作为字符串(否则您已经失去了精度其余的没有意义)。
现在,您需要将字符串拆分为更小的部分,足够小,以便任何剩余部分和一段字符串的串联可以容纳 9 位数字。
准备一个正则表达式来分割字符串
例如,如果
digits
为 7,则正则表达式为它匹配最大长度为 7 的非空子字符串,其后面是 (
(?=...)
是正向前瞻),字符数是 7 的倍数。“g”是使表达式遍历所有字符串,而不是在第一次匹配时停止。现在将每个部分转换为整数,并通过
reduce
计算余数(添加回之前的余数 - 或 0 - 乘以 10 的正确幂):由于“减法”余数算法,这将起作用:
它允许用余数替换数字十进制表示的任何“初始部分”,而不影响最终余数。
最终代码如下所示:
If you need to calculate the remainder for very large integers, which the JS runtime cannot represent as such (any integer greater than 2^32 is represented as a float and so it loses precision), you need to do some trick.
This is especially important for checking many case of check digits which are present in many instances of our daily life (bank account numbers, credit cards, ...)
First of all you need your number as a string (otherwise you have already lost precision and the remainder does not make sense).
You now need to split your string in smaller parts, small enough so the concatenation of any remainder and a piece of string can fit in 9 digits.
Prepare a regular expression to split the string
For instance, if
digits
is 7, the regexp isIt matches a nonempty substring of maximum length 7, which is followed (
(?=...)
is a positive lookahead) by a number of characters that is multiple of 7. The 'g' is to make the expression run through all string, not stopping at first match.Now convert each part to integer, and calculate the remainders by
reduce
(adding back the previous remainder - or 0 - multiplied by the correct power of 10):This will work because of the "subtraction" remainder algorithm:
which allows to replace any 'initial part' of the decimal representation of a number with its remainder, without affecting the final remainder.
The final code would look like:
如果您只是除以 2 的幂,则可以使用按位运算符:(
第一个是商,第二个是余数)
If you are just dividing with powers of two, you can use bitwise operators:
(The first is the quotient, the second the remainder)
如果您需要一些愚蠢的大数字的商,您可以使用:
注意:这只适用于
x
和y
值的情况,即被除数和除数,即使经过任何舍入以使它们大于Number.MAX_SAFE_INTEGER
时也可以作为整数工作,也能准确表示。例如,如果我们有:
那么本页给出的答案将为您提供:
正确答案是
90
,因此,如您所见,我上面给出的方程是唯一提供正确答案的方程回答。该方程也适用于负结果。如果我们将
x
设为负数,那么我们会得到:只有该方程和
Math.floor()
才能给出正确答案。并且,只是为了确认一些给出稍大值的不同值:
我们得到:
在这种情况下,Math.floor()和(x-(x%y))/y 失败,这意味着,虽然它可能不快或不漂亮,这个答案给出的代码是在所有情况下给出正确结果的唯一方法, 前提是除数和被除数是能够准确地表示出来。 (或者,至少是我所知道的所有情况。)
如果您想知道如何获得大数的正确余数,请参阅:
附录:如果您只处理正数,那么您可以将其缩短为这样:
If you need the quotient for some stupidly big numbers, you can use:
NOTE: This only works for cases where the
x
andy
values, i.e. the dividend and divisor, are represented accurately, even after any rounding to make them work as integers when they're larger thanNumber.MAX_SAFE_INTEGER
.For example, if we have:
Then the answers given on this page give you:
The correct answer is
90
, so, as you can see, the equation I gave above is the only one which provides a correct answer.The equation works for negative results as well. If we make
x
negative then we get:Only that equation and
Math.floor()
give the correct answers.And, just to confirm with some different values that give a slightly larger value:
we get:
In this case,
Math.floor()
and(x-(x%y))/y
fail, meaning that, while it may not be fast or pretty, the code given for this answer is the only method which gives correct results in all cases, provided that the divisor and dividend are able to be represented accurately. (Or, at least, all cases that I'm aware of.)If you want to know how to get the correct remainder for large numbers, see:
Addendum: If you're only working with positive numbers, then you can shorten it to this:
您还可以使用三元运算符来决定如何处理正整数值和负整数值。
如果该数字是正数,则一切正常。如果数字是负数,则会加 1,因为 Math.floor 处理负数的方式。
You can use the ternary operator to decide how to handle positive and negative integer values as well.
If the number is a positive, all is fine. If the number is a negative, it will add 1 because of how Math.floor handles negatives.
这将始终截断为零。
This will always truncate towards zero.
计算页数可以一步完成:
Calculating the number of pages may be done in one step:
这是一种方法来做到这一点。 (我个人不会这样做,但我认为这是一种有趣的示例方式。)前面的答案中提到的方法肯定更好,因为这调用了多个函数,因此速度较慢,并且会占用更多空间。
Here is a way to do this. (Personally I would not do it this way, but I thought it was a fun way to do it for an example.) The ways mentioned in previous answers are definitely better as this calls multiple functions and is therefore slower as well as takes up more room in your bundle.