11
  1. Javaでバイトをintに変換したい。バイトは符号なしバイトであると想定したい。仮に

    byte a = (byte)0xFF;
    
    int r = (some operation on byte a);
    

    r は、10 進数で -1 ではなく 255 にする必要があります。

  2. 次に、3 バイトから int 値を作成します。仮に

    byte b1 = (byte)0x0F;
    
    byte b2 = (byte)0xFF;
    
    byte b3 = (byte)0xFF;
    
    int r = (some operation in bytes b1, b2 and b3);
    

    次に、r は である必要があります0x000FFFFF。バイト b1 は int 値の上位 3 番目の位置に配置され、バイト b3 は下位 1 番目の位置に配置されます。また、バイトの符号なしの性質を想定して、私の b1 は 0x00 から 0x0F までの範囲になり、他のバイトは から0x00までになります。0xFFバイト b1 が 0x0F より大きい場合、下位 4 ビットのみを抽出します。つまり、3 バイトから int を抽出したいのですが、3 バイトのうち 20 ビットしか使用しません。(b2 と b3 の合計 16 ビット、および b1 の下位 4 ビット)。int r は、3 バイトから作成し、バイトの符号なしの性質を想定しているため、正でなければなりません。

4

5 に答える 5

6

ここでは符号拡張に注意する必要があります - 残念ながら、バイトは Java で署名されています (私の知る限り、これはただの悲しみの原因です)。

そのため、少しマスキングを行う必要があります。

int r = (b3 & 0xFF) | ((b2 & 0xFF) << 8) | ((b1 & 0x0F) << 16);
于 2012-10-31T09:31:24.697 に答える
3

符号なしのバイト値が必要だと思います

int r = ((b1 & 0xF) << 16) | ((b2 & 0xFF) << 8) | (b3 & 0xFF);

すべてのバイトをマスクして、正しいビットにシフトする必要があります。

于 2012-10-31T09:34:27.400 に答える
2

これは、ビットシフト演算子とバイナリANDを使用すると非常に簡単です。b1の下位4ビットのみを使用したいのですが、それがまさにその通りb1 & 0x0Fです。残りはすべてビットをさまざまな位置にシフトしています

int r = ( (b1 & 0x0F) << 16) + ((b2 & 0xFF) << 8) + (b3 & 0xFF)

@haroldが指摘したように編集すると、前者の解決策(下位バイトに0xFFマスクがない場合)は、符号拡張のために異常を引き起こしていました...

EDIT2おやおや、これらを処理するとき、私は常に演算子の優先順位によって顔を殴られます...

推奨読書:

于 2012-10-31T09:27:36.490 に答える
1

どちらが速いか気になったので、いくつかの回答を比較しました。

Bohemian の方法が最速のようですが、最初の実行でなぜ 11% 遅いのか説明できません。

PS .: 回答の正しさを確認しませんでした。

ここにコード:

public class Test
{

  public static void main(String[] args)
  {
    final int RUNS = 10;
    final int TRIPLE = 3;
    final int N = 100000000;

    byte[] bytes = new byte[TRIPLE * 32768]; // 96 kB

    Random r = new Random();
    r.nextBytes(bytes);

    List<ByteConvertTester> testers = Arrays.asList(new Harold(), new Bohemian(), new Ppeterka());

    for (int i = 0; i < RUNS; i++)
    {
      System.out.println("RUN#" + i);
      System.out.println("----------------------");
      Integer compare = null;
      for (ByteConvertTester tester : testers)
      {
        System.out.println(tester.getClass().getSimpleName());
        long time = testAndMeasure(tester, bytes, N);
        System.out.print("time (in ms): " + time);
        if (compare != null) {
          System.out.println(" SpeedUp%: " + (double) ((int) (10000 * (1.0d - (double) time / compare))) / 100);
        } else {
          compare = (int) time;
          System.out.println();
        }
      }
      System.out.println("----------------------");
    }
  }

  private static long testAndMeasure(ByteConvertTester bct, byte[] bytes, int loops)
  {
    Calendar start = Calendar.getInstance();
    int r;
    for (int i = 0; i < loops; i += 3)
      r = bct.test(bytes[i % bytes.length], bytes[(i + 1) % bytes.length], bytes[(i + 2) % bytes.length]);

    Calendar end = Calendar.getInstance();
    long time = (end.getTimeInMillis() - start.getTimeInMillis());
    return time;
  }
}

interface ByteConvertTester
{
  public int test(byte msb, byte mid, byte lsb);
}

class Harold implements ByteConvertTester
{
  @Override
  public int test(byte msb, byte mid, byte lsb)
  {
    return (lsb & 0xFF) | ((mid & 0xFF) << 8) | ((msb & 0x0F) << 16);
  }
}

class Bohemian implements ByteConvertTester
{
  @Override
  public int test(byte msb, byte mid, byte lsb)
  {
    return ((msb << 28) >>> 12) | (mid << 8) | lsb;
  }
}

class Ppeterka implements ByteConvertTester
{

  @Override
  public int test(byte msb, byte mid, byte lsb)
  {
    return ((msb & 0x0F) << 16) + ((mid & 0xFF) << 8) + (lsb & 0xFF);
  }
}

出力

RUN#0
----------------------
Harold
time (in ms): 489
Bohemian
time (in ms): 547 SpeedUp%: -11.86
Ppeterka
time (in ms): 479 SpeedUp%: 2.04
----------------------
RUN#1
----------------------
Harold
time (in ms): 531
Bohemian
time (in ms): 521 SpeedUp%: 1.88
Ppeterka
time (in ms): 537 SpeedUp%: -1.12
----------------------
RUN#2
----------------------
Harold
time (in ms): 531
Bohemian
time (in ms): 539 SpeedUp%: -1.5
Ppeterka
time (in ms): 532 SpeedUp%: -0.18
----------------------
RUN#3
----------------------
Harold
time (in ms): 529
Bohemian
time (in ms): 519 SpeedUp%: 1.89
Ppeterka
time (in ms): 531 SpeedUp%: -0.37
----------------------
RUN#4
----------------------
Harold
time (in ms): 527
Bohemian
time (in ms): 519 SpeedUp%: 1.51
Ppeterka
time (in ms): 530 SpeedUp%: -0.56
----------------------
RUN#5
----------------------
Harold
time (in ms): 528
Bohemian
time (in ms): 519 SpeedUp%: 1.7
Ppeterka
time (in ms): 532 SpeedUp%: -0.75
----------------------
RUN#6
----------------------
Harold
time (in ms): 529
Bohemian
time (in ms): 520 SpeedUp%: 1.7
Ppeterka
time (in ms): 532 SpeedUp%: -0.56
----------------------
RUN#7
----------------------
Harold
time (in ms): 529
Bohemian
time (in ms): 520 SpeedUp%: 1.7
Ppeterka
time (in ms): 533 SpeedUp%: -0.75
----------------------
RUN#8
----------------------
Harold
time (in ms): 530
Bohemian
time (in ms): 521 SpeedUp%: 1.69
Ppeterka
time (in ms): 532 SpeedUp%: -0.37
----------------------
RUN#9
----------------------
Harold
time (in ms): 529
Bohemian
time (in ms): 527 SpeedUp%: 0.37
Ppeterka
time (in ms): 530 SpeedUp%: -0.18
----------------------
于 2013-08-21T11:40:33.457 に答える
1

「シフトのみ」のバージョンは次のとおりです。

int r = ((b1 << 28) >>> 12) | (b2 << 8) | b3;

28 ビットを左にシフトすると上位 4 ビットが切り捨てられ、次に 12 ビットを右にシフトすると正味の 16 ビットの左シフトに戻ります。

私はこのコードをテストしましたが、動作します:)

于 2012-10-31T09:26:41.497 に答える