15

アプリケーション フレームワークでは、複数の Int 値 (通常は列挙型の代わりに使用される) を関数に渡すことができるフレームワークをよく見かけます。

例えば:

public class Example
{ 
    public class Values
    {
        public static final int ONE = 0x7f020000;
        public static final int TWO = 0x7f020001;
        public static final int THREE = 0x7f020002;
        public static final int FOUR = 0x7f020003;
        public static final int FIVE = 0x7f020004;
    }

    public static void main(String [] args)
    {
        // should evaluate just Values.ONE
        Example.multiValueExample(Values.ONE);

        // should evalueate just values Values.ONE,  Values.THREE, Values.FIVE
        Example.multiValueExample(Values.ONE | Values.THREE | Values.FIVE);

        // should evalueate just values Values.TWO , Values.FIVE
        Example.multiValueExample(Values.TWO | Values.FIVE);
    }

    public static void multiValueExample(int values){
        // Logic that properly evaluates bitwise values
        ...
    }
}

では、ビットごとの演算子を使用して渡された複数の int 値を適切に評価するには、multiValueExample にどのようなロジックが存在する必要がありますか?

4

8 に答える 8

32

値は 2 のべき乗である必要があります。

そうすれば、それらをビット単位で OR したときに情報が失われることはありません。

public static final int ONE   = 0x01;
public static final int TWO   = 0x02;
public static final int THREE = 0x04;
public static final int FOUR  = 0x08;
public static final int FIVE  = 0x10;

次に、これを行うことができます:

public static void main(String [] args) {
    Example.multiValueExample(Values.ONE | Values.THREE | Values.FIVE);
}

public static void multiValueExample(int values){
    if ((values & Values.ONE) == Values.ONE) {
    }

    if ((values & Values.TWO) == Values.TWO) {
    }

    // etc.
}
于 2009-03-15T15:56:21.140 に答える
9

既に述べたように、ビット値の代わりに列挙型の使用を検討してください。

効果的な Java 2によると: 「項目 32:ビット フィールドの代わりにEnumSetを使用する」

EnumSetの使用は、メモリ使用量に対して非常に効果的であり、非常に便利です。

次に例を示します。

package enums;

import java.util.EnumSet;
import java.util.Set;

public class Example {
  public enum Values {
    ONE, TWO, THREE, FOUR, FIVE
  }

  public static void main(String[] args) {
    // should evaluate just Values.ONE
    Example.multiValueExample(EnumSet.of(Values.ONE));

    // should evalueate just values Values.ONE, Values.THREE, Values.FIVE
    Example.multiValueExample(EnumSet.of(Values.ONE, Values.THREE, Values.FIVE));

    // should evalueate just values Values.TWO , Values.FIVE
    Example.multiValueExample(EnumSet.of(Values.TWO, Values.FIVE));
  }

  public static void multiValueExample(Set<Values> values) {
    if (values.contains(Values.ONE)) {
      System.out.println("One");
    }

    // Other checks here...

    if (values.contains(Values.FIVE)) {
      System.out.println("Five");
    }
  }
}
于 2009-03-15T19:20:28.700 に答える
7

整数値を 2 の累乗になるように設定して、列挙された各値が 2 進数表現の 1 ビットになるようにします。

int ONE = 0x1;    //0001
int TWO = 0x2;    //0010
int THREE = 0x4;  //0100
int FOUR = 0x8;   //1000

次に、ビット単位の OR を使用して値を結合し、ビット単位の AND を使用してセット値をテストします。

int test_value = (ONE | FOUR);   //-> 1001
bool has_one = (test_value & ONE) != 0;  //-> 1001 & 0001 -> 0001 -> true
于 2009-03-15T16:01:29.787 に答える
4

| と組み合わせる値 (バイナリ OR、論理 OR [||] ではない) は、ビット表現に「1」が重複してはなりません。例えば、

ONE = 0x1 =   0000 0001
TWO = 0x2 =   0000 0010
THREE = 0x3 = 0000 0011
FOUR = 0x4 =  0000 0100

次に、ONE と TWO を組み合わせることができます。たとえば、次のようになります。

ONE | TWO = 0000 0011

しかし、あなたは一つを区別することはできません | 重複するビットがあるため、3 つから 2 つ。したがって、結合する数値は 2 のべき乗である必要があり、OR 演算を行ったときに重複しないようにする必要があります。数値が「値」に渡されたかどうかをテストするには、次のようにします。

if (values & ONE) {
    // ... then ONE was set
}

これがなぜどのように機能するのかをよりよく理解するために、バイナリ表現とロジックについて少し読むことをお勧めします。良いところは、Art of Assembly の Chapter 3 です

于 2009-03-15T16:00:28.290 に答える
3

まず、ビットごとの比較を行うように値を定義することはできません。代わりに、別のビットを設定します。

public static final int ONE   = 0x1;  // First bit is set
public static final int TWO   = 0x2;  // Second bit is set
public static final int THREE = 0x4;  // Third bit is set
public static final int FOUR  = 0x8;  // Fourth bit is set
public static final int FIVE  = 0x10; // Fifth bit is set

次に、おそらく次のような操作にはjava.util.BitSetを使用する必要があります。

BitSet bits = new BitSet(5);
bits.set(2);
bits.set(4);

System.out.println("these bits are set: " + bits);
// Prints "these bits are set: {2, 4}"

BitSet otherBits = new BitSet(5);
otherBits.set(3);
otherBits.set(4);

System.out.println("these bits are set: " + bits.or(otherBits));
// Prints "these bits are set: {2, 3, 4}"
于 2009-03-15T16:00:17.120 に答える
3

それらが 2 の累乗である場合、以下のコードの「display」メソッドのようなことを行います。

これは、2の累乗が必要な理由を説明するトピックに関するウィキペディアのリンクです。

public class Main
{
    private static final int A = 0x01;
    private static final int B = 0x02;
    private static final int C = 0x04;

    public static void main(final String[] argv)
    {
        display(A);
        display(B);
        display(C);
        display(A | A);
        display(A | B);
        display(A | C);
        display(B | A);
        display(B | B);
        display(B | C);
        display(C | A);
        display(C | B);
        display(C | C);
        display(A | A | A);
        display(A | A | B);
        display(A | A | C);
        display(A | B | A);
        display(A | B | B);
        display(A | B | C);
        display(A | C | A);
        display(A | C | B);
        display(A | C | C);
        display(B | A | A);
        display(B | A | B);
        display(B | A | C);
        display(B | B | A);
        display(B | B | B);
        display(B | B | C);
        display(B | C | A);
        display(B | C | B);
        display(B | C | C);
        display(C | A | A);
        display(C | A | B);
        display(C | A | C);
        display(C | B | A);
        display(C | B | B);
        display(C | B | C);
        display(C | C | A);
        display(C | C | B);
        display(C | C | C);
    }

    private static void display(final int val)
    {
        if((val & A) != 0)
        {
            System.out.print("A");
        }

        if((val & B) != 0)
        {
            System.out.print("B");
        }

        if((val & C) != 0)
        {
            System.out.print("C");
        }

        System.out.println();
    }
}
于 2009-03-15T16:08:55.120 に答える
3

すべてのビットがカウントされるとき、ビット マスクの使用は一般的でした。今日これを行う別の方法は、操作と拡張がより簡単な列挙型を使用することです。

import static Example.Values.*;
import java.util.Arrays;

public class Example {
    public enum Values { ONE, TWO, THREE, FOUR, FIVE }

    public static void main(String [] args) {
        // should evaluate just Values.ONE
        multiValueExample(ONE);

        // should evaluate just values Values.ONE,  Values.THREE, Values.FIVE
        multiValueExample(ONE, THREE, FIVE);

        // should evaluate just values Values.TWO , Values.FIVE
        multiValueExample(TWO, FIVE);
    }

    public static void multiValueExample(Values... values){
        // Logic that properly evaluates
        System.out.println(Arrays.asList(values));
        for (Values value : values) {
            // do something.
        }
    }
}
于 2009-03-15T18:18:31.687 に答える
0

ビット演算に関する Java チュートリアルの章は、次の場所にあります。

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html

非常に簡潔ですが、参考にしてください。

于 2009-03-15T16:16:28.097 に答える