二进制长除法算法

时间:2013-12-17 14:54:01

标签: java algorithm binary division

我一直在尝试在java中重新创建以下算法:

Set quotient to 0
Align leftmost digits in dividend and divisor
Repeat
If that portion of the dividend above the divisor is greater than or equal to the divisor
Then subtract divisor from that portion of the dividend and
Concatentate 1 to the right hand end of the quotient
Else concatentate 0 to the right hand end of the quotient
Shift the divisor one place right
Until dividend is less than the divisor
quotient is correct, dividend is remainder
STOP

这也可以在这里找到:

Long division in binary

这是我的代码:

public class Division {
    public static void main(String[] args) {
        int quotient =0;
        int a = 123;
        int b = 5;
        int bfirst = b;
        String a1 = Integer.toBinaryString(a);
        String b1 = Integer.toBinaryString(b);
        int aLength = a1.length();
        int bLength = b1.length();
        int power = aLength - bLength;
        b =(int) Math.pow(b, power);    

        while(a > bfirst) {
            if(a >= b) {
                a = a-b;
                quotient = quotient*2+1;
                b = b/2;
            } else {
                quotient = quotient*2;
                b = b/2;
            }
        }
        System.out.println(quotient);
    }
}

它有时会返回正确的答案,但有时则不会。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

我相信

b = (int) Math.pow(b, power);    

应该是

b = (int) (b * Math.pow(2, power));

变量b似乎是要与之比较的当前数字,并被a减去。你正在进行二元除法,在这一行之后的代码中,我发现这个值只被除以2.在这种情况下,Math.pow(b, power)没有意义。


此外,还有一个缺失的步骤。因为a - b会将所有值降低到最后并获得a < bFirst,所以所有结束的零都不计入商,因为我们已经退出循环。

替换

a = a-b;
quotient = quotient*2+1;
b = b/2;

bLength = Integer.toBinaryString(b).length();
int bfirstLength = Integer.toBinaryString(bfirst).length();
a = a-b;
quotient = quotient*2+1;
b = b/2;
if (a < bfirst) {
    quotient = quotient * (int)Math.pow(2, bLength - bfirstLength);
}

考虑商的缺失零。


此外还有一个错误。

while (a > bfirst) {

应该是

while (a >= bfirst) {

如果a可以被b整除,则应该进行长除法并减去剩余的红利,而不是停止该过程。


最后,数字中的二进制数字的数量可以通过

计算
(int) (Math.ln(a) / Math.ln(2)) + 1

最后,尝试在调试时使用算法中的System.out.println,它会有很多帮助,让您准确地知道算法出错的地方。更好的是,如果您知道如何并且可用(通常集成到IDE中),请使用调试器。

而且,最后一个,在编码之前用一些例子手工完成算法 - 这绝对可以帮助你理解算法是如何工作的。

整个事情,使用调试语句:http://ideone.com/JBzHdf

答案 1 :(得分:1)

您的算法不太正确。如果商具有尾随零,则会失败,因为循环在附加它们之前停止。一个正确的算法是:

let q = 0
shift divisor left until divisor > dividend (k bits)
while k > 0
  k = k - 1
  divisor = divisor >> 1
  if dividend >= divisor
     q = (q << 1) + 1
     dividend = dividend - sd
  else
     q = q << 1
return q

你应该使用整数(实际上是long)和移位运算符<<>>。它们使字符串操作更容易(更不用说更快)。

由于已经接受了答案,因此如果感兴趣,这里是上述算法的Java。

public static long div(long dividend, long divisor) {
    long quotient = 0;
    int k = 0;
    while (divisor <= dividend && divisor > 0) {
        divisor <<= 1;
        k++;
    }
    while (k-- > 0) {
        divisor >>= 1;
        if (divisor <= dividend) {
            dividend -= divisor;
            quotient = (quotient << 1) + 1;
        }
        else quotient <<= 1;
    }
    return quotient;
}