[英]How to perform an integer division, and separately get the remainder, in JavaScript?
在JavaScript中,我如何獲得:
對於一些數字y
和一些除數x
計算商 ( quotient
) 和remainder
數 ( remaining ) 為:
var quotient = Math.floor(y/x);
var remainder = y % x;
我不是按位運算符的專家,但這是獲得整數的另一種方法:
var num = ~~(a / b);
這也適用於負數,而Math.floor()
將朝錯誤的方向舍入。
這似乎也是正確的:
var num = (a / b) >> 0;
我在 Firefox 上做了一些速度測試。
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
以上基於每個 1000 萬次試驗。
結論:使用(a/b>>0)
(或(~~(a/b))
或(a/b|0)
)可實現約 20% 的效率增益。 還要記住,當a/b<0 && a%b!=0
時,它們都與Math.floor
不一致。
ES6 引入了新的Math.trunc
方法。 這允許修復@MarkElliot 的答案,使其也適用於負數:
var div = Math.trunc(y/x);
var rem = y % x;
請注意,與位運算符相比, Math
方法的優勢在於它們可以處理超過 2 31的數字。
我通常使用:
const quotient = (a - a % b) / b;
const remainder = a % b;
它可能不是最優雅的,但它確實有效。
var remainder = x % y;
return (x - remainder) / y;
您可以使用函數parseInt
來獲取截斷的結果。
parseInt(a/b)
要獲得余數,請使用 mod 運算符:
a%b
parseInt 對字符串有一些陷阱,以避免使用基數為 10 的基數參數
parseInt("09", 10)
在某些情況下,數字的字符串表示可以是科學計數法,在這種情況下,parseInt 會產生錯誤的結果。
parseInt(100000000000000000000000000000000, 10) // 1e+32
此調用將產生 1 作為結果。
Math.floor(operation)
返回運算的向下舍入值。
第一個問題的例子:
const x = 5; const y = 10.4; const z = Math.floor(x + y); console.log(z);
第二個問題的例子:
const x = 14; const y = 5; const z = Math.floor(x % y); console.log(x);
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:進入 = -28,余數 = -0.3800000000000079
是的,我注意到了,那里有一個精度問題,但我沒有時間檢查它(我不知道這是 Firefox、Windows 7 還是我的 CPU 的 FPU 的問題)。 不過,對於 Yarin 的問題,它只涉及整數,gammax 的代碼可以完美運行。
const idivmod = (a, b) => [a/b |0, a%b];
還有一個關於它的提案Modulus and Additional Integer Math
Alex Moore-Niemi的評論作為答案:
對於來自 Google 的 Rubyists 搜索divmod
,您可以這樣實現它:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
結果:
// [2, 33]
您可以使用 javascript 中的 Math.floor function 進行運算。 Math.floor 將返回商,% 將返回余數。
const quotient = Math.floor(a/b);
const remainder = a % b;
如果您只是用 2 的冪除,則可以使用位運算符:
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 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 Quotient of two value
console.log(divide.division) //to get Floating division of two value
console.log(divide.Remainder) //to get Remainder of two value
console.log(divide.calculate()) //to get object containing all the values
您也可以使用三元來決定如何處理正整數和負整數值。
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
如果這個數字是正數,一切都很好。 如果數字是負數,它會加 1,因為 Math.floor 處理負數的方式。
這將始終截斷為零。 不知道是否為時已晚,但它是這樣的:
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
};
}
計算頁數可以一步完成:Math.ceil(x/y)
如果您需要計算 JS 運行時無法表示的非常大整數的余數(任何大於 2^32 的整數都表示為浮點數,因此它會失去精度),您需要做一些技巧。
這對於檢查我們日常生活中許多情況中存在的許多校驗位(銀行帳號、信用卡等)尤為重要
首先,您需要將您的數字作為字符串(否則您已經失去了精度並且其余的沒有意義)。
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);
}
這是一種方法。 (我個人不會這樣做,但我認為這是一個有趣的例子)
function intDivide(numerator, denominator) { return parseInt((numerator/denominator).toString().split(".")[0]); } let x = intDivide(4,5); let y = intDivide(5,5); let z = intDivide(6,5); console.log(x); console.log(y); console.log(z);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.