小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目描述
给定两个整数,被除数
dividend
和除数divisor
。将两数相除,要求不使用乘法、除法和 mod 运算符。返回被除数
dividend
除以除数divisor
得到的商。整数除法的结果应当截去(
truncate
)其小数部分,例如:truncate(8.345) = 8
以及truncate(-2.7335) = -2
- 被除数和除数均为 32 位有符号整数
- 除数不为 0
- 假设我们的环境只能存储 32 位有符号整数,其数值范围是
[−2^31, 2^31 − 1]
。本题中,如果除法结果溢出,则返回2^31 − 1
示例1 :
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333..) = truncate(3) = 3
示例2 :
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333..) = -2
思路1:位运算
分析:x>>i
相当于x/2^i
,x<<i
相当于x*2^i
var divide = function(dividend, divisor) {
if (divisor === 0) return Infinity;
if (dividend === 0) return 0;
if (dividend === -2147483648 && divisor === -1) return 2147483647;
let res = 0;
let flag = '';
if (dividend < 0 && divisor > 0 || dividend > 0 && divisor < 0) {
flag = '-';
}
dividend = Math.abs(dividend);
divisor = Math.abs(divisor);
while (dividend >= divisor) {
let temp = divisor, m = 1;
while (temp <= (dividend >> 1)) { // 位运算模拟乘法,撑到最大。防止溢出
temp <<= 1;
m <<= 1;
}
dividend -= temp;
res += m;
}
return parseInt(flag + res);
};
思路2:ES6模拟
var divide = function(dividend, divisor) {
if (!dividend) return 0
let res = 0, isNegative = (dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)
const MIN = 0 - 2 ** 31, MAX = 2 ** 31 - 1
let l1 = Math.abs(dividend).toString().length
let l2 = Math.abs(divisor).toString().length
let p = [], rest = '', curP = 0
for (let i = 0; i <= l1 - l2; i++) {
p[i] = 0
let curNum = `${rest}${Math.abs(dividend).toString().substring(curP, l2 + i) * 1}`
while (curNum >= Math.abs(divisor)) {
curNum -= Math.abs(divisor)
p[i] ++
}
rest = curNum
curP = l2 + i
}
res = p.join('') * 1
res = isNegative ? 0 - res : res
if (res > MAX) res = MAX
if (res < MIN) res = MIN
return res
};
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤