14

1つの整数を通過してから2つの整数の値を取得する必要がある2つの整数があります。

論理演算子(AND、OR、XORなど)の使用を考えています。

4

5 に答える 5

15

C プログラミング言語を使用すると、2 つの整数が 65535 未満であると仮定して、次のように実行できます。

void take2IntegersAsOne(int x)
{
   // int1 is stored in the bottom half of x, so take just that part.
   int int1 = x & 0xFFFF;  

   // int2 is stored in the top half of x, so slide that part of the number
   // into the bottom half, and take just that part.
   int int2 = (x >> 16) & 0xFFFF

   // use int1 and int2 here. They must both be less than 0xFFFF or 65535 in decimal

}


void pass2()
{
  int int1 = 345;
  int int2 = 2342;
  take2Integers( int1 | (int2 << 16) );
}

これは、C では整数が 4 バイトで格納されるという事実に依存しています。したがって、この例では、最初の 2 バイトを使用して整数の 1 つを格納し、次の 2 バイトを 2 番目の整数に格納します。これは制限を課しますが、それぞれの整数は、それぞれがわずか 2 バイトに収まるように十分に小さい値を持つ必要があります。

シフト演算子 << および >> は、整数のビットを上下にスライドさせるために使用されます。16 シフトすると、ビットが 2 バイト移動します (1 バイトあたり 8 ビットであるため)。

0xFFFF を使用すると、数値の下位 2 バイトのすべてのビットが 1 であるビット パターンを表します。そのため、ANDing (& 演算子を使用) により、これらの下位 2 バイトに含まれていないすべてのビットがオフになります (ゼロに戻ります)。 )。これを使用して、現在抽出している整数から「他の整数」の任意の部分を削除できます。

于 2011-01-19T17:31:19.483 に答える
6

この質問には 2 つの部分があります。まず、2 つの 32 ビット整数をビットマスクして 64 ビット長整数にする方法を教えてください。

他の人が述べているように、X 座標と Y 座標を取り、その Point の線形値を表す倍長整数を返す関数があるとします。私はこの 2 次元データの線形化を次のように呼ぶ傾向があります。

public long asLong(int x, int y) {
    return ( ((long)x) << 32 ) | y;
}

public int getX(long location) {
    return (int)((location >> 32) & 0xFFFFFFFF);
}

public int getY(long location) {
    return (int)(location & 0xFFFFFFFF);
}

操作の順序について偏執的である場合はご容赦ください。他の操作が << よりも貪欲である場合があり、必要以上に物事がシフトすることがあります。

なぜこれが機能するのですか?いつ失敗する可能性がありますか? 整数が倍長整数のちょうど半分のサイズになる傾向があるのは便利です。ここで行っているのは、x を long にキャストし、y の左側に完全に配置されるまで左にシフトしてから、ユニオン演算 (OR) を実行して両方のビットを結合することです。

それらが 8 ビットの数値に結合される 4 ビットの数値であるとしましょう。

x = 14     :      1110
y =  5     :      0101

x = x << 4 : 1110 0000

p = x | y  : 1110 0000
           OR     0101
             ---------
             1110 0101

一方、逆:

p = 229    : 1110 0101  
x = p >> 4 : 1111 1110  //depending on your language and data type, sign extension
                        //can cause the bits to smear on the left side as they're
                        //shifted, as shown here. Doesn't happen in unsigned types
x = x & 0xF:
             1111 1110
         AND 0000 1111
         -------------
             0000 1110  //AND selects only the bits we have in common

y = p & 0xF:
             1110 0101
         AND 0000 1111
         -------------
             0000 0101  //AND strikes again

この種のアプローチは、ストレージまたは伝送スペースからすべてのビットを絞り出す必要がある環境で、ずっと前に生まれました。組み込みシステムを使用していない場合、またはネットワーク経由で送信するためにこのデータをすぐにパックしている場合、この手順全体の実用性は急速に低下し始めます。

  • ほとんどの場合すぐにボックス化解除して呼び出し元が読み取る必要がある戻り値をボックス化するためだけに、あまりにも多くの作業が必要です。それは、穴を掘ってから埋めるようなものです。
  • コードの可読性が大幅に低下します。「返される型は?」ええと... int.. と別の int... long で。
  • 追跡が困難なバグが発生する可能性があります。たとえば、符号なしの型を使用して符号拡張を無視する場合は、後でそれらの型が 2 の補数になるプラットフォームに移行します。倍長整数を保存して、後でコードの別の部分で読み取ろうとすると、ビットシフトで off-by-one エラーが発生し、関数のデバッグに 1 時間費やして、パラメーターが間違っていることがわかります。

それがとても悪い場合、代替手段は何ですか?

これが、人々があなたの言語について尋ねてきた理由です。理想的には、C や C++ などを使用している場合は、次のように言うのが最善です。

struct Point { int x; int y; };

public Point getPosition() {
    struct Point result = { 14,5 };
    return result;
}

そうしないと、Java のような HLL では、同じ機能を実現するために内部クラスが必要になる可能性があります。

public class Example {
    public class Point {
        public int x;
        public int y;
        public Point(int x, int y) { this.x=x; this.y=y; }
    }

    public Point getPosition() {
        return new Point(14,5);
    }
}

この場合、getPosition は Example.Point を返します。Point を頻繁に使用し続ける場合は、Point を独自の完全なクラスに昇格させます。実際、java.awt には、Point や Point.Float など、すでにいくつかの Point クラスがあります。

最後に、最近の多くの言語には、複数の値をタプルにボックス化するか、関数から複数の値を直接返すためのシンタックス シュガーがあります。これは一種の最終手段です。私の経験では、データが本来のものではないふりをするたびに、後で問題が発生します。しかし、メソッドが絶対に同じデータの一部ではない2 つの数値を返さなければならない場合は、タプルまたは配列が適しています。

c++ stdlib タプルのリファレンスは、 http: //www.cplusplus.com/reference/std/tuple/ にあります。

于 2012-10-22T17:05:00.390 に答える
2

まあ.. @Feliceは正しいですが、両方が16ビットに収まる場合は方法があります:

output_int = (first_int << 16) | second_int
                               ^
                           means 'or'

それらを梱包し、

first_int = output_int & 0xffff
second_int = (output int >> 16) & 0xffff
                                ^
                           means 'and'

それらを抽出します。

于 2011-01-19T17:29:03.920 に答える
1

2 つの整数が 1 つの整数に収まらないか、少なくとも 2 つの元の整数を取り戻すことはできません。
とにかく、元の 2 つの整数が特定のビット数に制限されている場合 (疑似コードで): 最初の整数 OR with (2 番目の整数 SHIFTLEFT(nOfBits))

2 つの整数マスクを取得するには、マージされた整数を nOfBitsOne で表されるバイナリの数値でマスクします。最初の整数を取得し、マージされた整数を nOfBits で ShiftRight すると、2 番目の整数が返されます。

于 2011-01-19T17:25:51.000 に答える
-1

32 ビット整数内に 2 つの 16 ビット整数を格納できます。最初のものは最初の 16 ビットで、2 つ目は最後の 16 ビットです。値を取得して構成するには、シフト演算子を使用します。

于 2011-01-19T17:29:38.780 に答える