【问题标题】:Adding 2 BitSets in Java在 Java 中添加 2 个 BitSet
【发布时间】:2012-07-27 05:45:51
【问题描述】:

嗯,我需要在 java 中添加两个 BitSet .. 我已经尝试使用 XOR(求和)和 AND(用于进位)的基本运算进行添加 .. 考虑进位 ..

但答案并不完全正确...... 这是我尝试过的..

public static BitStorage Add(int n, BitStorage ...manyBitSets)
{
    BitStorage sum = new BitStorage(0, n);      //discarding carry out of MSB
    System.out.print("Addition of: ");
    for(BitStorage bitStorage:manyBitSets)
    {
        //System.out.print(sum+"\t");
        //System.out.print(bitStorage+"\t");
        System.out.println("~~~~~");
        for(int i=n-1;i>=0;i--)
        {
            if(i==n-1)
            {
                System.out.println(sum + " + " +bitStorage);
                sum.set(i, sum.get(i)^bitStorage.get(i));
                //System.out.println(sum.get(i)+" XOR "+bitStorage.get(i));
            }
            else
            {
                System.out.println(sum + " + " +bitStorage+"\t"+(sum.get(i)?"1":"0"+"^"+(bitStorage.get(i)?"1":"0")+"^"+(sum.get(i+1)?"1":"0"+"&"+(bitStorage.get(i+1)?"1":"0"))));
                sum.set(i, sum.get(i)^bitStorage.get(i)^(sum.get(i+1)&bitStorage.get(i+1)));      //carry taken here
                //System.out.println(sum.get(i)+" XOR "+bitStorage.get(i)+" XOR ("+bitStorage.get(i+1)+" AND "+sum.get(i+1));
            }
        }
    }   
    return sum;
}

PS:BitStorage 类不过是 BitSet 的自己的实现,带有一些额外的方法 .. 例如 Add、Subtract、Shift 等

它有 2 个成员:

  1. 一个整数 (n) 作为最大大小(我不希望向量的增长或收缩影响按位操作 => 因此所有操作都在 n 完成)-> 例如:n 为 4,然后位占据位置 o 到 3 in位集
  2. 一个大小为 n 的 BitSet 对象传入构造函数

还有2分:

  • 我想将其转换为长数组或字节数组,然后添加,但我只需要在 JDK 6 而不是 7 中的解决方案
  • 我不需要从 MSB 生成的进位,我希望答案是相同的 no(bits),即 n

很抱歉多次使用“我想要...”.. 有点累。 .尝试了很多东西! 嗯,我需要这个作为算法的一部分.. 期待回复.. :) :)

【问题讨论】:

  • 虽然我很高兴能像这样展示你的所有代码......请解释为什么这“不太正确”......你得到的答案是不正确的?
  • 我花了一段时间才明白发生了什么,但我终于弄明白了。如果下次包含一个简短的示例调用会有所帮助。你的进位坏了,所以你总是设置错误的位。
  • @BillJames 谢谢! . .and 嗯嗯,包括进位在内的许多附加功能都有问题..
  • @SilverbackNet 嗯是的.. 我想通了.. 过了一段时间我发布了这个问题..

标签: java bit-manipulation bitwise-operators bits


【解决方案1】:

我累了,如果它很丑,请原谅我。你的携带方法完全被破坏了并且设置了错误的位,即使它不应该设置任何东西。您应该向上计数,因此,没有理由对最后一位进行特殊处理,进位就会消失。通过实际将最后一个结果带到下一个循环迭代中,逻辑要简单得多。

public static BitStorage Add(int n, BitStorage ...manyBitSets)
{
    BitStorage sum = new BitStorage(0, n);      //discarding carry out of MSB
    System.out.print("Addition of: ");
    for(BitStorage bitStorage:manyBitSets)
    {
        boolean carry = false;
        boolean lastcarry = false;
        //System.out.print(sum+"\t");
        //System.out.print(bitStorage+"\t");
        System.out.println("~~~~~");
        for(int i=0;i<n;i++)
        {
                System.out.println(sum + " + " +bitStorage+"\t"+(sum.get(i)?"1":"0"+"^"+(bitStorage.get(i)?"1":"0")+"^"+(sum.get(i+1)?"1":"0"+"&"+(bitStorage.get(i+1)?"1":"0"))));
                lastcarry = carry;
                carry = sum.get(i) && bitStorage.get(i);
                sum.set(i, lastcarry^sum.get(i)^bitStorage.get(i));      //carry taken here
                //System.out.println(sum.get(i)+" XOR "+bitStorage.get(i)+" XOR ("+bitStorage.get(i+1)+" AND "+sum.get(i+1));
        }
    }   
    return sum;
}

我对变量使用布尔值,因为我将类构建为 BitSet 上的一个瘦包装器,如果您使用 int 或其他任何东西而不是更改它们。

【讨论】:

  • 谢谢!为您的帖子:) .. 我有一段时间离线.. 正在吃午饭.. 一边想着这个.. .我没有尝试你的方式..但我想我会保留它作为未来的其他选择..到目前为止,我发现了这个错误..并实现了我自己的另一个逻辑..答案也是正确的! :) 无论如何感谢您的回答! :)
【解决方案2】:

嗯,这是一个有趣的问题,让我猜测了一段时间......

我无法先推导出逻辑,但后来我切换回基础知识并推导出 boolean expression 以计算 3 位运算的求和和进位,这是解决方案:

public static BitSet addBitSet(int n, List<BitSet> bitSetList){
    BitSet sumBitSet = new BitSet(n);
    for (BitSet firstBitSet : bitSetList) {
        BitSet secondBitSet = (BitSet) sumBitSet.clone();
        System.out.println("A:  " + printBitSet(firstBitSet, 6));
        System.out.println("B:  " + printBitSet(secondBitSet, 6));
        boolean carryForNext = false, sum,a,b,c;
        for (int i = n - 1; i >= 0; i--) {
            a=firstBitSet.get(i);
            b=secondBitSet.get(i);
            c=carryForNext;
            sum = a&!b&!c|!a&!b&c|!a&b&!c|a&b&c;
            carryForNext = a&b&!c|a&!b&c|!a&b&c|a&b&c;
            sumBitSet.set(i,sum);
        }
        System.out.println("SUM:" + printBitSet(sumBitSet, 6));
    }
    System.out.println(printBitSet(sumBitSet, 6));
    return sumBitSet;
}

这是printBitSet的代码:

public static String printBitSet(BitSet bitSet, int size) {
    StringBuilder builder = new StringBuilder("");
    for (int i = 0; i < size; i++) {
        if (bitSet.get(i))
            builder.append("1");
        else
            builder.append("0");
    }
    return builder.toString();
}

【讨论】:

  • 感谢您的帖子! :) .. 但我发现了那里的错误 .. 并实现了我自己的花药逻辑! :) .. 和我的打印 BitSet 逻辑也是一样的 :P .. 除了我覆盖了 toString! :P .. 我会保留你的方式作为未来的选择 .. 无论如何感谢你的回答! :)
  • 太好了。它让我思考了一段时间。请接受这个问题的答案。
【解决方案3】:

我发现了错误..这是携带的问题.. 而是使用相同的逻辑..我选择了另一个逻辑.. 只是对两个数字进行异或(得到总和)..并再次将其视为一个数字,将其添加到具有进位的数字(从原始数字与运算中获得).. AND 输出(进位)在每次迭代中左移.. 因为 LSB 侧位加法没有任何要添加的进位

当进位位集全为 0(假)时,我们停止循环

一个例子:

  1. 0001
  2. +0011
  3. =0010 -->(XOR = sum)
  4. +0010 -->(AND输出=进位..左移后显示,现在将添加到XOR输出)
  5. =0000 -->(XOR = sum)
  6. +0100 -->(AND输出=进位..左移后显示,现在将添加到XOR输出)
  7. =0100 -->(XOR = sum .. 最终答案)
  8. 0000 -->(AND 输出 = 进位 .. 左移后显示 .. 我们停在这里 .. 停止,因为都是 0))

一个样本:)

import java.util.*;
public class BitSetAddition
{
static String nums[] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};
public static void main(String args[])
{
    for(int q=0;q<nums.length;q++)
    {
        System.out.print(q+1+" -> ");
        BitSet b1 = new BitSet();
        String s = nums[q];
        b1.set(0, s.charAt(0)=='1'?true:false);
        b1.set(1, s.charAt(1)=='1'?true:false);
        b1.set(2, s.charAt(2)=='1'?true:false);
        b1.set(3, s.charAt(3)=='1'?true:false);

        for(int i=0;i<4;i++)
            System.out.print(b1.get(i)?"1":"0");
            System.out.print(" + ");

        BitSet b2 = new BitSet();
        String a = "0001";
        b2.set(0, a.charAt(0)=='1'?true:false);
        b2.set(1, a.charAt(1)=='1'?true:false);
        b2.set(2, a.charAt(2)=='1'?true:false);
        b2.set(3, a.charAt(3)=='1'?true:false);

        for(int i=0;i<4;i++)
            System.out.print(b2.get(i)?"1":"0");
            System.out.print(" = ");

        BitSet sum = new BitSet();
        BitSet carry = new BitSet();
        BitSet toAdd = new BitSet();
        BitSet tempSum = new BitSet();
        BitSet tempCarry = new BitSet();

        sum = b1;
        toAdd = b2;
        do
        {
            copy(4, tempSum, sum);
            copy(4, tempCarry, toAdd);
            tempSum.xor(toAdd);
            tempCarry.and(sum);
            copy(4, sum, tempSum);
            copy(4, carry, leftShift(4, tempCarry));
            copy(4, toAdd, carry);
            //sum.set(i, b1.get(i)^b2.get(i)^(b1.get(i+1)&b2.get(i+1)));
        }while(!carry.equals(new BitSet()));
            //if(i+2<=3)
                //sum.set(i, b1.get(i)^b2.get(i)^(b1.get(i+1)&b2.get(i+1)&(b1.get(i+2)&(b2.get(i+2)))));
            //else if(i+1<=3)
                //sum.set(i, b1.get(i)^b2.get(i)^(b1.get(i+1)&b2.get(i+1)));
            //else
                //sum.set(i, b1.get(i)^b2.get(i));
        for(int i=0;i<4;i++)
            System.out.print(sum.get(i)?"1":"0");

        System.out.println();
    }
}
static void copy(int n,BitSet b, BitSet toCopy)
{
    for(int i=0;i<n;i++)
        b.set(i, toCopy.get(i));
}
static BitSet leftShift(int n, BitSet b)
{
    for(int i=0;i<n;i++)
        b.set(i, b.get(i+1));
        b.set(n-1, false);
        return b;
}
}

程序中的 cmets 是我之前的逻辑 .. 我发现我之前的逻辑更复杂 :P .. 如果需要,请忽略程序的 cmets :)

注意:我不想要 MSB 位加法产生的进位 .. 根据算法(我需要这个).. 所以答案(总和)具有相同的位数..任何人都可以根据需要进行调整:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 2018-06-07
    • 1970-01-01
    • 2016-09-01
    • 2012-12-11
    相关资源
    最近更新 更多