在JavaScript中,我如何获得以下内容:
1. 一个给定整数被另一个整数整除的次数? 2. 余数?
1. 一个给定整数被另一个整数整除的次数? 2. 余数?
Alex Moore-Niemi的评论作为答案:
如果你是从 Google 搜索 divmod
而来的 Ruby 开发者,可以按照以下方式实现:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
结果:
// [2, 33]
str = '123456789123456789123456789'
现在你需要将字符串分成更小的部分,足够小,以便于任何剩余部分和一个字符串片段的连接可以适合9个数字。
digits = 9 - String(divisor).length
准备一个正则表达式来拆分字符串
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
digits
是7,则正则表达式为/.{1,7}(?=(.{7})+$)/g
该正则表达式匹配长度最长为7的非空子字符串,后面跟随着((?=...)
是一个正向先行断言)多个字符,其数量是7的倍数。 'g' 是为了使表达式运行到所有字符串上,而不是在第一次匹配时停止。
现在将每个部分转换为整数,并通过 reduce
计算余数(将以前的余数 - 或 0 - 乘以正确的10的幂再加回来):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
n mod d = (n - kd) mod d
该功能允许将数字的“初始部分”替换为其余数,而不影响最终余数。
最终代码如下:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
div
(计算除法的商)和mod
(计算除法的余数)有几种可能的定义,满足以下约束条件:
Number.isInteger(div(x, y))
;x === div(x, y) * y + mod(x, y)
;Math.abs((mod(x, y)) < Math.abs(y)
。这些定义在计算机科学文献和编程语言中的常见用法基于
截断除法:
function div(x, y) {
return Math.trunc(x / y);
}
function mod(x, y) {
return x % y;
}
向下取整除法:
function div(x, y) {
return Math.floor(x / y);
}
function mod(x, y) {
return ((x % y) + y) % y;
}
欧几里得除法:
function div(x, y) {
return Math.sign(y) * Math.floor(x / Math.abs(y));
}
function mod(x, y) {
const z = Math.abs(y);
return ((x % z) + z) % z;
}
mod(x, y) * x >= 0
;
- 地板除法具有以下特性:mod(x, y) * y >= 0
;
- 欧几里得除法具有以下特性:mod(x, y) >= 0
。x >= 0
且 y > 0
,则截断、地板和欧几里得除法相同;
- 如果 x >= 0
且 y < 0
,则截断和欧几里得除法相同;
- 如果 x <= 0
且 y > 0
,则地板和欧几里得除法相同;
- 如果 x <= 0
且 y < 0
,则截断和地板除法相同。quotient = dividend / divisor | 0;
remainder = dividend % divisor;
如果你只是按二次幂进行除法运算,你可以使用位运算符:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
。 - Palecfunction integerDivison(dividend, divisor) {
this.Division = dividend/divisor;
this.Quotient = Math.floor(dividend/divisor);
this.Remainder = dividend%divisor;
this.calculate = () => {
return {Value:this.Division, Quotient:this.Quotient, Remainder:this.Remainder};
}
}
var divide = new integerDivison(5, 2);
console.log(divide.Quotient) // To get the quotient of two values
console.log(divide.division) // To get the floating division of two values
console.log(divide.Remainder) // To get the remainder of two values
console.log(divide.calculate()) // To get the object containing all the values
Math.trunc((x/y) + (Number.EPSILON * (2 ** Math.ceil(Math.log2(Math.abs(x/y))))) * Math.sign(x/y))
注意:这仅适用于情况,其中x
和y
值,即被除数和除数,在进行舍入后仍然准确表示,以便在它们大于Number.MAX_SAFE_INTEGER
时作为整数工作。
例如,如果我们有:
x = 45000000000000000000000000000 = 4.5e+28
y = 500000000000000000000000000 = 5e+26
89.99999999999999: x/y
90: Math.trunc((x/y) + (Number.EPSILON * (2 ** Math.ceil(Math.log2(Math.abs(x/y))))) * Math.sign(x/y))
89: Math.floor(x/y)
89: ~~(x/y)
89: (x/y)>>0
89: x/y|0
89: (x-(x%y))/y
-89.99999999999999: x/y
-90: Math.trunc((x/y) + (Number.EPSILON * (2 ** Math.ceil(Math.log2(Math.abs(x/y))))) * Math.sign(x/y))
-90: Math.floor(x/y)
-89: ~~(x/y)
-89: (x/y)>>0
-89: x/y|0
-89: (x-(x%y))/y
x = -45000000000000000000000000 = -4.5e+25
y = 500000000000000000000000 = 5e+23
-90.00000000000001: x/y
-90: Math.trunc((x/y) + (Number.EPSILON * (2 ** Math.ceil(Math.log2(Math.abs(x/y))))) * Math.sign(x/y))
-91: Math.floor(x/y)
-90: ~~(x/y)
-90: (x/y)>>0
-90: x/y|0
-90.00000000000001: (x-(x%y))/y
Math.floor()
和(x-(x%y))/y
都会失败,这意味着,虽然可能不快也不美观,但本答案中给出的代码是唯一能在所有情况下给出正确结果的方法,前提是被除数和除数能够准确表示。(或者至少是我所知道的所有情况。)Math.trunc((x/y) + (Number.EPSILON * (2 ** Math.ceil(Math.log2(x/y)))))
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
计算页面数量可以在一步完成:
Math.ceil(x/y)
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
divmod
函数使用向下取整的除法(Math.floor
),当涉及负数时与截断除法(Math.trunc
)不同。这适用于NPMdivmod
包、Rubydivmod
、SWI-Prologdivmod
和很可能许多其他实现也是如此。 - Palecdivmod
存在是因为它的执行速度是分别计算这两个操作的两倍。提供这样一个没有这种性能优势的函数可能会令人困惑。 - Palec