在 java 中不使用乘法、除法和 mod 运算符来除两个整数
Divide two integers without using multiplication, division and mod operator in java
我写下了一个代码,它在两个数相除后找出商,但没有使用乘法、除法或 mod 运算符。
我的代码
public int divide(int dividend, int divisor) {
int diff=0,count=0;
int fun_dividend=dividend;
int fun_divisor=divisor;
int abs_dividend=abs(dividend);
int abs_divisor=abs(divisor);
while(abs_dividend>=abs_divisor){
diff=abs_dividend-abs_divisor;
abs_dividend=diff;
count++;
}
if(fun_dividend<0 && fun_divisor<0){
return count;
}
else if(fun_divisor<0||fun_dividend<0) {
return (-count);
}
return count;
}
我的代码通过了 dividend=-1、divisor=1 或 dividend=1 and divisor=-1 等测试用例。但是不能通过dividend = --2147483648 and divisor =-1这样的测试用例。但是,当两个输入均为负时,我有一个 if 语句。
if(fun_dividend<0 && fun_divisor<0){
return count;
}
当我输入 -2147483648 和 -1 时,它返回零。我调试了我的代码,发现它无法到达 while 循环的内部语句。它只是检查 while 循环并终止并执行
if(fun_dividend<0 && fun_divisor<0){
return count;
}
很明显,两个输入都是负数,所以我使用 Math.abs
函数使它们为正数。但是当我试图查看变量 abs_dividend 和 abs_divisor 的值时,它们显示负值。
Integer max 可以取 9 位数字。那么我怎样才能通过这个测试用例呢?根据这个测试用例,红利是一个 10 位数字,它对整数范围无效。
根据测试用例,我得到的输出应该是 2147483647。
我该如何解决该错误?
提前谢谢你。
运行 用调试器发现 abs_dividend
是-2147483648.
那么 while (abs_dividend >= abs_divisor) {
中的比较是错误的并且 count
永远不会递增。
原来解释在 Math.abs(int a)
的 Javadoc 中:
Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.
据推测,这是因为 Integer.MAX_VALUE
是 2147483647,所以无法用 int
表示正数 2147483648。 (注意:2147483648 将是 Integer.MAX_VALUE + 1 == Integer.MIN_VALUE
)
尝试为此使用位操作,如下所示:
public static int divideUsingBits(int dividend, int divisor) {
// handle special cases
if (divisor == 0)
return Integer.MAX_VALUE;
if (divisor == -1 && dividend == Integer.MIN_VALUE)
return Integer.MAX_VALUE;
// get positive values
long pDividend = Math.abs((long) dividend);
long pDivisor = Math.abs((long) divisor);
int result = 0;
while (pDividend >= pDivisor) {
// calculate number of left shifts
int numShift = 0;
while (pDividend >= (pDivisor << numShift)) {
numShift++;
}
// dividend minus the largest shifted divisor
result += 1 << (numShift - 1);
pDividend -= (pDivisor << (numShift - 1));
}
if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0)) {
return result;
} else {
return -result;
}
}
我是这样解决的。在左移时有可能溢出的地方,优先选择数据类型 long
而不是 int
。在一开始就处理边缘情况,以避免在此过程中修改输入值。该算法基于我们在学校使用的除法技术。
public int divide(int AA, int BB) {
// Edge case first.
if (BB == -1 && AA == Integer.MIN_VALUE){
return Integer.MAX_VALUE; // Very Special case, since 2^31 is not inside range while -2^31 is within range.
}
long B = BB;
long A = AA;
int sign = -1;
if ((A<0 && B<0) || (A>0 && B>0)){
sign = 1;
}
if (A < 0) A = A * -1;
if (B < 0) B = B * -1;
int ans = 0;
long currPos = 1; // necessary to be long. Long is better for left shifting.
while (A >= B){
B <<= 1; currPos <<= 1;
}
B >>= 1; currPos >>= 1;
while (currPos != 0){
if (A >= B){
A -= B;
ans |= currPos;
}
B >>= 1; currPos >>= 1;
}
return ans*sign;
}
我写下了一个代码,它在两个数相除后找出商,但没有使用乘法、除法或 mod 运算符。
我的代码
public int divide(int dividend, int divisor) {
int diff=0,count=0;
int fun_dividend=dividend;
int fun_divisor=divisor;
int abs_dividend=abs(dividend);
int abs_divisor=abs(divisor);
while(abs_dividend>=abs_divisor){
diff=abs_dividend-abs_divisor;
abs_dividend=diff;
count++;
}
if(fun_dividend<0 && fun_divisor<0){
return count;
}
else if(fun_divisor<0||fun_dividend<0) {
return (-count);
}
return count;
}
我的代码通过了 dividend=-1、divisor=1 或 dividend=1 and divisor=-1 等测试用例。但是不能通过dividend = --2147483648 and divisor =-1这样的测试用例。但是,当两个输入均为负时,我有一个 if 语句。
if(fun_dividend<0 && fun_divisor<0){
return count;
}
当我输入 -2147483648 和 -1 时,它返回零。我调试了我的代码,发现它无法到达 while 循环的内部语句。它只是检查 while 循环并终止并执行
if(fun_dividend<0 && fun_divisor<0){
return count;
}
很明显,两个输入都是负数,所以我使用 Math.abs
函数使它们为正数。但是当我试图查看变量 abs_dividend 和 abs_divisor 的值时,它们显示负值。
Integer max 可以取 9 位数字。那么我怎样才能通过这个测试用例呢?根据这个测试用例,红利是一个 10 位数字,它对整数范围无效。
根据测试用例,我得到的输出应该是 2147483647。
我该如何解决该错误?
提前谢谢你。
运行 用调试器发现 abs_dividend
是-2147483648.
那么 while (abs_dividend >= abs_divisor) {
中的比较是错误的并且 count
永远不会递增。
原来解释在 Math.abs(int a)
的 Javadoc 中:
Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.
据推测,这是因为 Integer.MAX_VALUE
是 2147483647,所以无法用 int
表示正数 2147483648。 (注意:2147483648 将是 Integer.MAX_VALUE + 1 == Integer.MIN_VALUE
)
尝试为此使用位操作,如下所示:
public static int divideUsingBits(int dividend, int divisor) {
// handle special cases
if (divisor == 0)
return Integer.MAX_VALUE;
if (divisor == -1 && dividend == Integer.MIN_VALUE)
return Integer.MAX_VALUE;
// get positive values
long pDividend = Math.abs((long) dividend);
long pDivisor = Math.abs((long) divisor);
int result = 0;
while (pDividend >= pDivisor) {
// calculate number of left shifts
int numShift = 0;
while (pDividend >= (pDivisor << numShift)) {
numShift++;
}
// dividend minus the largest shifted divisor
result += 1 << (numShift - 1);
pDividend -= (pDivisor << (numShift - 1));
}
if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0)) {
return result;
} else {
return -result;
}
}
我是这样解决的。在左移时有可能溢出的地方,优先选择数据类型 long
而不是 int
。在一开始就处理边缘情况,以避免在此过程中修改输入值。该算法基于我们在学校使用的除法技术。
public int divide(int AA, int BB) {
// Edge case first.
if (BB == -1 && AA == Integer.MIN_VALUE){
return Integer.MAX_VALUE; // Very Special case, since 2^31 is not inside range while -2^31 is within range.
}
long B = BB;
long A = AA;
int sign = -1;
if ((A<0 && B<0) || (A>0 && B>0)){
sign = 1;
}
if (A < 0) A = A * -1;
if (B < 0) B = B * -1;
int ans = 0;
long currPos = 1; // necessary to be long. Long is better for left shifting.
while (A >= B){
B <<= 1; currPos <<= 1;
}
B >>= 1; currPos >>= 1;
while (currPos != 0){
if (A >= B){
A -= B;
ans |= currPos;
}
B >>= 1; currPos >>= 1;
}
return ans*sign;
}