5

私はC++プログラムをJavaに変換していますが、次の方法で完全に行き詰まり、頭がおかしくなりました。この方法が何をしているのか説明していただけませんか?

long TSBCA::GetSignedValue(const NDataString &value)
    {
       static NDataString s;    
       s = value;

       long multiplier(1);
       size_t len(s.Len());
       if (len != 0)
       {
          if (s[0] >= (char)0xB0 && s[0] <= (char)0xB9)
          {
             s[0] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else if (s[len - 1] >= (char)0xB0 && s[len - 1] <= (char)0xB9)
          {
             s[len - 1] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else
             multiplier = 1;
       }
       else
          multiplier = 1;
       return s.ToLong() * multiplier;
    }

編集:

私の最初のJavaバージョン:

private long getSignedValue(final String value){

       byte[] bytes = value.getBytes();
       int length = bytes.length;
       long multiplier = 1L;

       if (bytes.length > 0){
          if (bytes[0] >= (char)0xB0 && bytes[0] <= (char)0xB9){


             bytes[0] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else if (bytes[length - 1] >= (char)0xB0 && bytes[length - 1] <= (char)0xB9)
          {
              bytes[length - 1] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else
             multiplier = 1;
       }
       else
          multiplier = 1;
       return Long.parseLong(Arrays.toString(bytes))* multiplier;
}

私はそれを正しくしましたか?

4

3 に答える 3

1

バイト文字列 (つまり、テキストではない) を取得し、long に変換しています。多くの実装固有のものに依存しており、壊れているように見えます。2 つの異なる場所から符号ビットを抽出しています。もう 1 つの問題は、不必要な再入不可 (静的変数が原因) です。

于 2009-12-01T21:20:34.677 に答える
1
s[0] &= 0x7F;

bit-ands[0]と hex を意味7Fします。つまり、バイト値から符号ビットを取り除きます。と同じs[len-1]なので、次のようになります。

  • 最初または最後の桁に符号ビットが追加された数値文字列を取ります ( 0x30- 0x39== '0'-'9'および0xB0-0xB90x80ビット セットと同じ範囲です)。
  • 符号ビットを取り除き、それを乗数として記憶します
  • 乗数を使用して数値文字列引数を解釈し、符号を設定します
  • その値を返します

編集

コードを確認すると、次のコメントが表示されます。

  • 意図したとおりに動作しない場合は、新しいコードの JUnit テストをいくつか作成して、期待どおりに動作することを確認してください。
  • マジック ナンバーを個別の定数に配置する
  • byteバイトと比較するときに定数を使用する(符号の問題)
  • ぶら下がっている他のものは中括弧を取得する必要があり、この場合は不要です
  • new String(byte[])Arrays ユーティリティ クラスではなく、文字列を再構築するために使用します。

これは私をこのバージョンに導きます:

// Bit Pattern: 0111 1111
private static final int BYTE_7F = 0x7F;

// '0' with sign bit set
private static final byte BYTE_NEGATIVE_0 = (byte) 0xB0;

// '9' with sign bit set
private static final byte BYTE_NEGATIVE_9 = (byte) 0xB9;


private long getSignedValue(String value) {

    byte[] bytes = value.getBytes();
    final int length = bytes.length;
    long multiplier = 1;

    if (0 < length) {
        if (bytes[0] >= BYTE_NEGATIVE_0 && bytes[0] <= BYTE_NEGATIVE_9) {

            bytes[0] &= BYTE_7F; 
            multiplier = -1;

        } else if (bytes[length - 1] >= BYTE_NEGATIVE_0 && bytes[length - 1] <= BYTE_NEGATIVE_9) {
            bytes[length - 1] &= BYTE_7F;
            multiplier = -1;
        }
    }

    return Long.parseLong(new String(bytes)) * multiplier;
}

正しいコメントを追加することに注意を払い、定数名を更新してドキュメントの用語に合わせる必要があります。

于 2009-12-01T21:23:03.757 に答える
0

奇妙なバージョンのサイン (正または負) をテストしているようです。最初または最後の (しかしできれば最初の) 文字が と の間0xB00xB9ある場合は、その文字の最上位ビットをハックします ( と の間0x300x39から までの数字に'0'します'9')。次に、通常の人間が知っているように、マイナス記号を付けて数値を返します。

于 2009-12-01T21:24:42.653 に答える