Java中的二进制算术运算法则

5
在理论上,二进制算法很简单,但是作为一名初学者,我发现在二进制数的加、减、乘、除方面编写算法有些困难。我有两个以字符串形式存储的二进制数,假设任何前导零都已被删除。如何对这两个数字执行这些操作呢?请注意:我需要避免将它们转换为int或long。

1
你想学习如何实现实际算法,还是只是对这些字符串进行算术运算? - Daff
2
https://dev59.com/UHM_5IYBdhLWcg3wzmrL - paxdiablo
Daff,我想学习如何实现这个算法。 - Tyler Treat
6个回答

11

将二进制字符串转换为整数:

int i = Integer.parseInt("10101011", 2);
int j = Integer.parseInt("00010", 2);

那么你可以随心所欲地处理这两个整数,例如:

i = i + j;
i = i - j;

并将它们转换回二进制字符串:

String s = Integer.toBinaryString(i);

抱歉,我应该注意到需要避免将它们转换为int或long。 - Tyler Treat

5
算法,来自维基百科:
加法:

The simplest arithmetic operation in binary is addition. Adding two single-digit binary numbers is relatively simple, using a form of carrying:

0 + 0 → 0
0 + 1 → 1
1 + 0 → 1
1 + 1 → 0, carry 1 (since 1 + 1 = 0 + 1 × 10 in binary)

Adding two "1" digits produces a digit "0", while 1 will have to be added to the next column.

减法:

Subtraction works in much the same way:

0 − 0 → 0
0 − 1 → 1, borrow 1
1 − 0 → 1
1 − 1 → 0

Subtracting a "1" digit from a "0" digit produces the digit "1", while 1 will have to be subtracted from the next column. This is known as borrowing. The principle is the same as for carrying. When the result of a subtraction is less than 0, the least possible value of a digit, the procedure is to "borrow" the deficit divided by the radix (that is, 10/10) from the left, subtracting it from the next positional value.

乘法:

Multiplication in binary is similar to its decimal counterpart. Two numbers A and B can be multiplied by partial products: for each digit in B, the product of that digit in A is calculated and written on a new line, shifted leftward so that its rightmost digit lines up with the digit in B that was used. The sum of all these partial products gives the final result.

Since there are only two digits in binary, there are only two possible outcomes of each partial multiplication:

* If the digit in B is 0, the partial product is also 0
* If the digit in B is 1, the partial product is equal to A

For example, the binary numbers 1011 and 1010 are multiplied as follows:

          1 0 1 1   (A)
        × 1 0 1 0   (B)
        ---------
          0 0 0 0   ← 对应B中的零
  +     1 0 1 1     ← 对应B中的一
  +   0 0 0 0
  + 1 0 1 1      
  --------------- 
  = 1 1 0 1 1 1 0


4
以下代码实现了二进制加法,而不需要进行任何算术运算,无论是二进制还是其他。实际的“加法”由lookupTable完成,其余所有内容都是纯字符串操作。我编写它的目的是尽可能地使它具有教学性,强调过程而不是效率。希望能对你有所帮助。
public class BinaryArithmetic {
    static String[] lookupTable = {
        "0+0+0=00",
        "0+0+1=01",
        "0+1+0=01", 
        "0+1+1=10",
        "1+0+0=01",
        "1+0+1=10",
        "1+1+0=10",
        "1+1+1=11",
    };
    static String lookup(char b1, char b2, char c) {
        String formula = String.format("%c+%c+%c=", b1, b2, c);
        for (String s : lookupTable) {
            if (s.startsWith(formula)) {
                return s.substring(s.indexOf("=") + 1);
            }
        }
        throw new IllegalArgumentException();
    }
    static String zeroPad(String s, int length) {
        while (s.length() < length) {
            s = "0" + s;
        }
        return s;
    }   
    static String add(String s1, String s2) {
        int length = Math.max(s1.length(), s2.length());
        s1 = zeroPad(s1, length);
        s2 = zeroPad(s2, length);
        String result = "";
        char carry = '0';
        for (int i = length - 1; i >= 0; i--) {
            String columnResult = lookup(s1.charAt(i), s2.charAt(i), carry);
            result = columnResult.charAt(1) + result;
            carry = columnResult.charAt(0);
        }
        if (carry == '1') {
            result = carry + result;
        }
        return result;
    }
    public static void main(String args[]) {
        System.out.println(add("11101", "1001"));
    }
}

顺便说一下,我也可以做 multiply

static String multiply(String s1, String s2) {
    String result = "";
    String zeroSuffix = "";
    for (int i = s2.length() - 1; i >= 0; i--) {
        if (s2.charAt(i) == '1') {
            result = add(result, s1 + zeroSuffix);
        }
        zeroSuffix += "0";
    }
    return result;
}

2

与十进制相比,使用二进制算术并没有什么不同。让我们以加法为例。

                 (1)     (1)
182      182      182      182      182
845      845      845      845      845
--- +    --- +    --- +    --- +    --- +
           7       27      027     1027

那么你做了什么?你将数字右对齐以进行加法,然后从右到左逐位相加,在必要时向左进位+1。

在二进制中,这个过程完全相同。事实上,它甚至更简单,因为现在你只有两个“数字”,0和1!

             (1)                           (1)       (1)
11101      11101      11101      11101      11101      11101      11101
 1001       1001       1001       1001       1001       1001       1001 
----- +    ----- +    ----- +    ----- +    ----- +    ----- +    ----- +
               0         10        110       0110      00110     100110

其余操作也同样类似:您在十进制中使用的过程,在二进制中同样适用。而且,实际上更简单,因为只有两个“数字”,0和1。这种简单性是硬件喜欢二进制系统的原因。

1
将二进制字符串转换为整数,然后对整数进行操作,例如:
String add(String s1, String s2) {
    int i1 = Integer.parseInt(s1);
    int i2 = Integer.parseInt(s2);
    return Integer.toBinaryString(i1 + i2);
}

0

内置的BitSet类非常直观易用,适用于位级操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接