1

そのため、intのフィールドを取得してから、それを拡張することに問題があります。int のフィールドを取得するメソッドがあります。

getField(int value, int hi, int lo);

Value はフィールドの取得元の int で、hi と lo はフィールドのサイズです。

したがって、この getField メソッドを getFieldSignExtended(int value, int hi, int lo) 内で呼び出すことができますが、それを符号拡張するにはどうすればよいでしょうか?

例えばvalue = 7, hi = 1, lo = 0

getField(7, 1, 0);バイナリの 7 は 111 で、hi と lo は 0 から 1 のフィールドを取るため、3 を返します。

getField から 3 が返されると、値が 0x0003 に等しいことがわかります。

私がこれまでに持っているものは、ポジティブなものでは機能しますが、ネガティブなものでは大きく台無しになります. そして、「めちゃめちゃ」と言うときは、まったく機能しないことを意味します。したがって、-1 で使用しようとすると、負ではなく大きな int として表示されます。

助けてくれてありがとう!:]

編集:申し訳ありませんが、私は自分自身とあなたの何人かを矛盾した声明で混乱させました:P. 修理済み。

4

2 に答える 2

2

ここで行われている行間は非常に多くの読み物です。ただし、 3 が返され、 returnとreturngetField(7, 1, 0)が必要な場合は、これが目的である可能性があります。getFieldSignExtended(15, 2, 0)-3getFieldSignExtended(3, 2, 0)+3

概念は、元の値のビット hi:lo からの n ビット フィールドを 2 の補数として扱うことです。n ビットの最初のビットが 1 の場合、n ビット フィールドを負の数として扱います。3 ビット フィールドの最初のビットが 0 の場合は、それを正の数として扱います。

#include <assert.h>
#include <limits.h>
#include <stdio.h>

extern int getFieldSignExtended(int value, int hi, int lo);

enum { INT_BITS = CHAR_BIT * sizeof(int) };

int getFieldSignExtended(int value, int hi, int lo)
{
    assert(lo >= 0);
    assert(hi > lo);
    assert(hi < INT_BITS - 1);
    int bits = (value >> lo) & ((1 << (hi - lo + 1)) - 1);
    if (bits & (1 << (hi - lo)))
        return(bits | (~0U << (hi - lo)));
    else
        return(bits);
}

3 つのアサーションは単純明快です。唯一物議を醸しているのは、コードがビット 31 の処理を​​拒否していることです。hi = 31 および lo = 0 で呼び出した場合、シフト (hi - lo + 1) が大きすぎて、動作が未定義になります。また、負の数を右にシフトするという実装定義の動作にも遭遇します。&これらの問題は、符号なし整数引数を取り、 if 操作を行わないことで解決できますhi - lo + 1 == INT_BITS。問題の修正は、読者の課題として残されています。

への代入bitsは値を右にシフトし、正しいビット数でマスクします。(1 << (hi - lo + 1)) - 1は、フィールド内のビット数より 1 だけ多く左に 1 をシフトし、次に 1 を減算して、フィールド内の各ビット位置に対してバイナリ 1 のストリングを生成します。たとえば、hi = 2、lo = 0 の場合、これは 1 を左に 3 桁シフトし、バイナリ 1000 を生成します。1 を引くと 0111 になるため、正しい 3 ビットが選択されます。したがって、bitsn ビット整数の適切なビット セットが含まれます。

このifテストでは、n ビット整数の最上位ビットが設定されているかどうかをチェックします。符号ビットが設定されていない場合は、単純に value を返しますbits。符号ビットが設定されている場合、実行するトリッキーな計算があります。これは、この回答の最初のドラフトで (非常に) 間違っていました。3 ビット = 101 のフィールドがあるとします。3 ビットの 2 の補数として、-3 を表します。フルサイズの を生成するには、これをすべて 1 で左に拡張する必要があります-1。の値~0はすべてビット 1 です。それがビット単位で左にシフトさhi - loれると、値の非符号ビットに一連のゼロが残ります。だけ左にシフトした場合も機能しますが、必要ではないhi - lo + 1余分な計算が必要です。+ 1

このテスト ハーネスを使用して、コードが正しく機能していることを確認しました。体系的なテストの出力は厳密です (小さい数値に対して)。これにより、計算値が期待値と一致することが保証されます。「徹底的な」テストは完全ではありません。1 つの値のみをテストし、問題 (たとえば、hi = 31 と lo = 0 を使用すると私のマシンで 0 という誤った答えが返されるなど) とパターンを観察するためのものです。

static const struct
{
    int  value;
    int  hi;
    int  lo;
    int  wanted;
} tests[] =
{
    {   0x0F,  1,  0,   -1 },
    {   0x0F,  2,  0,   -1 },
    {   0x0F,  2,  1,   -1 },
    {   0x0F,  3,  1,   -1 },
    {   0x0F,  4,  2,   +3 },
    {   0x0F,  5,  0,  +15 },
    {   0x0F,  5,  1,   +7 },
    {   0x0F,  5,  2,   +3 },
    {   0x0F,  5,  3,   +1 },
    {   0x0F,  5,  4,    0 },
    {   0x03,  2,  0,   +3 },
    {   0xF3,  2,  0,   +3 },
    {   0xF3,  3,  0,   +3 },
    {   0xF3,  4,  0,  -13 },
    {   0xF3,  5,  0,  -13 },
    {   0xF3,  6,  0,  -13 },
    {   0xF3,  7,  0,  -13 },
    {   0xF3,  7,  1,   -7 },
    {   0xF3,  7,  2,   -4 },
    {   0xF3,  7,  3,   -2 },
    {   0xF3,  7,  4,   -1 },
    {   0xF3,  8,  0, 0xF3 },
};
enum { NUM_TESTS = sizeof(tests) / sizeof(tests[0]) };
static const char s_pass[] = "== PASS ==";
static const char s_fail[] = "!! FAIL !!";

static void systematic_test(void)
{
    int fail = 0;
    for (int i = 0; i < NUM_TESTS; i++)
    {
        char const *pf = s_fail;
        int actual = getFieldSignExtended(tests[i].value, tests[i].hi, tests[i].lo);
        if (actual == tests[i].wanted)
            pf = s_pass;
        else
            fail++;
        printf("%s GFSX(%+4d = 0x%.4X, %d, %d) = %+4d = 0x%.8X (wanted %+4d = 0x%.8X)\n",
               pf, tests[i].value, tests[i].value, tests[i].hi, tests[i].lo, actual, actual,
               tests[i].wanted, tests[i].wanted);
    }
    printf("%s\n", (fail == 0) ? s_pass : s_fail);
}

static void exhaustive_test(void)
{
    int value = 0x5FA03CE7;
    for (int i = 1; i < INT_BITS - 1; i++)
    {
        for (int j = 0; j < i; j++)
        {
            int actual = getFieldSignExtended(value, i, j);
            printf("%11sGFSX(%d = 0x%X, %2d, %2d) = %+10d = 0x%.8X\n", "",
                    value, value, i, j, actual, actual);
        }
    }
}

int main(void)
{
    int result1 = getFieldSignExtended(15, 2, 0);
    int result2 = getFieldSignExtended( 3, 2, 0);
    printf("GFSX(15, 2, 0) = %+d = 0x%.8X\n", result1, result1);
    printf("GFSX( 3, 2, 0) = %+d = 0x%.8X\n", result2, result2);

    printf("\nSystematic test\n");
    systematic_test();

    printf("\nExhaustive test\n");
    exhaustive_test();

    return(0);
}

これは、徹底的なテストの前のテスト コードの出力と、徹底的なテストからの出力の小さな選択です。

GFSX(15, 2, 0) = -1 = 0xFFFFFFFF
GFSX( 3, 2, 0) = +3 = 0x00000003

Systematic test
== PASS == GFSX( +15 = 0x000F, 1, 0) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 2, 0) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 2, 1) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 3, 1) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 4, 2) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX( +15 = 0x000F, 5, 0) =  +15 = 0x0000000F (wanted  +15 = 0x0000000F)
== PASS == GFSX( +15 = 0x000F, 5, 1) =   +7 = 0x00000007 (wanted   +7 = 0x00000007)
== PASS == GFSX( +15 = 0x000F, 5, 2) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX( +15 = 0x000F, 5, 3) =   +1 = 0x00000001 (wanted   +1 = 0x00000001)
== PASS == GFSX( +15 = 0x000F, 5, 4) =   +0 = 0x00000000 (wanted   +0 = 0x00000000)
== PASS == GFSX(  +3 = 0x0003, 2, 0) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 2, 0) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 3, 0) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 4, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 5, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 6, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 7, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 7, 1) =   -7 = 0xFFFFFFF9 (wanted   -7 = 0xFFFFFFF9)
== PASS == GFSX(+243 = 0x00F3, 7, 2) =   -4 = 0xFFFFFFFC (wanted   -4 = 0xFFFFFFFC)
== PASS == GFSX(+243 = 0x00F3, 7, 3) =   -2 = 0xFFFFFFFE (wanted   -2 = 0xFFFFFFFE)
== PASS == GFSX(+243 = 0x00F3, 7, 4) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX(+243 = 0x00F3, 8, 0) = +243 = 0x000000F3 (wanted +243 = 0x000000F3)
== PASS ==

Exhaustive test
       GFSX(1604336871 = 0x5FA03CE7,  1,  0) =         -1 = 0xFFFFFFFF
       GFSX(1604336871 = 0x5FA03CE7,  2,  0) =         -1 = 0xFFFFFFFF
       GFSX(1604336871 = 0x5FA03CE7,  2,  1) =         -1 = 0xFFFFFFFF
       GFSX(1604336871 = 0x5FA03CE7,  3,  0) =         +7 = 0x00000007
       GFSX(1604336871 = 0x5FA03CE7,  3,  1) =         +3 = 0x00000003
       GFSX(1604336871 = 0x5FA03CE7,  3,  2) =         +1 = 0x00000001
       GFSX(1604336871 = 0x5FA03CE7,  4,  0) =         +7 = 0x00000007
       GFSX(1604336871 = 0x5FA03CE7,  4,  1) =         +3 = 0x00000003
       GFSX(1604336871 = 0x5FA03CE7,  4,  2) =         +1 = 0x00000001
       GFSX(1604336871 = 0x5FA03CE7,  4,  3) =         +0 = 0x00000000
       GFSX(1604336871 = 0x5FA03CE7,  5,  0) =        -25 = 0xFFFFFFE7
       GFSX(1604336871 = 0x5FA03CE7,  5,  1) =        -13 = 0xFFFFFFF3
       GFSX(1604336871 = 0x5FA03CE7,  5,  2) =         -7 = 0xFFFFFFF9
       GFSX(1604336871 = 0x5FA03CE7,  5,  3) =         -4 = 0xFFFFFFFC
       GFSX(1604336871 = 0x5FA03CE7,  5,  4) =         -2 = 0xFFFFFFFE
       GFSX(1604336871 = 0x5FA03CE7,  6,  0) =        -25 = 0xFFFFFFE7
       GFSX(1604336871 = 0x5FA03CE7,  6,  1) =        -13 = 0xFFFFFFF3
       GFSX(1604336871 = 0x5FA03CE7,  6,  2) =         -7 = 0xFFFFFFF9
       GFSX(1604336871 = 0x5FA03CE7,  6,  3) =         -4 = 0xFFFFFFFC
       GFSX(1604336871 = 0x5FA03CE7,  6,  4) =         -2 = 0xFFFFFFFE
       GFSX(1604336871 = 0x5FA03CE7,  6,  5) =         -1 = 0xFFFFFFFF
...
       GFSX(1604336871 = 0x5FA03CE7, 29, 28) =         +1 = 0x00000001
       GFSX(1604336871 = 0x5FA03CE7, 30,  0) = -543146777 = 0xDFA03CE7
       GFSX(1604336871 = 0x5FA03CE7, 30,  1) = -271573389 = 0xEFD01E73
       GFSX(1604336871 = 0x5FA03CE7, 30,  2) = -135786695 = 0xF7E80F39
       GFSX(1604336871 = 0x5FA03CE7, 30,  3) =  -67893348 = 0xFBF4079C
       GFSX(1604336871 = 0x5FA03CE7, 30,  4) =  -33946674 = 0xFDFA03CE
       GFSX(1604336871 = 0x5FA03CE7, 30,  5) =  -16973337 = 0xFEFD01E7
       GFSX(1604336871 = 0x5FA03CE7, 30,  6) =   -8486669 = 0xFF7E80F3
       GFSX(1604336871 = 0x5FA03CE7, 30,  7) =   -4243335 = 0xFFBF4079
       GFSX(1604336871 = 0x5FA03CE7, 30,  8) =   -2121668 = 0xFFDFA03C
       GFSX(1604336871 = 0x5FA03CE7, 30,  9) =   -1060834 = 0xFFEFD01E
       GFSX(1604336871 = 0x5FA03CE7, 30, 10) =    -530417 = 0xFFF7E80F
       GFSX(1604336871 = 0x5FA03CE7, 30, 11) =    -265209 = 0xFFFBF407
       GFSX(1604336871 = 0x5FA03CE7, 30, 12) =    -132605 = 0xFFFDFA03
       GFSX(1604336871 = 0x5FA03CE7, 30, 13) =     -66303 = 0xFFFEFD01
       GFSX(1604336871 = 0x5FA03CE7, 30, 14) =     -33152 = 0xFFFF7E80
       GFSX(1604336871 = 0x5FA03CE7, 30, 15) =     -16576 = 0xFFFFBF40
       GFSX(1604336871 = 0x5FA03CE7, 30, 16) =      -8288 = 0xFFFFDFA0
       GFSX(1604336871 = 0x5FA03CE7, 30, 17) =      -4144 = 0xFFFFEFD0
       GFSX(1604336871 = 0x5FA03CE7, 30, 18) =      -2072 = 0xFFFFF7E8
       GFSX(1604336871 = 0x5FA03CE7, 30, 19) =      -1036 = 0xFFFFFBF4
       GFSX(1604336871 = 0x5FA03CE7, 30, 20) =       -518 = 0xFFFFFDFA
       GFSX(1604336871 = 0x5FA03CE7, 30, 21) =       -259 = 0xFFFFFEFD
       GFSX(1604336871 = 0x5FA03CE7, 30, 22) =       -130 = 0xFFFFFF7E
       GFSX(1604336871 = 0x5FA03CE7, 30, 23) =        -65 = 0xFFFFFFBF
       GFSX(1604336871 = 0x5FA03CE7, 30, 24) =        -33 = 0xFFFFFFDF
       GFSX(1604336871 = 0x5FA03CE7, 30, 25) =        -17 = 0xFFFFFFEF
       GFSX(1604336871 = 0x5FA03CE7, 30, 26) =         -9 = 0xFFFFFFF7
       GFSX(1604336871 = 0x5FA03CE7, 30, 27) =         -5 = 0xFFFFFFFB
       GFSX(1604336871 = 0x5FA03CE7, 30, 28) =         -3 = 0xFFFFFFFD
       GFSX(1604336871 = 0x5FA03CE7, 30, 29) =         -2 = 0xFFFFFFFE
于 2012-12-07T01:49:55.200 に答える
0

取るべきアプローチは複数あります。始めたばかりの場合は、フィールドのビット数を算術的に計算できます。たとえば、次のようになります。

if (value %2 >= 1)
{
    // you know that the value has a `1` as the lest significant digit. 
    // if that's one of the digits you're looking for, you can do something like count++ here
}
else
{
    // least significant digit is a '0'
}

その後

if (value % 4 >=2)
{
    // you know that the second least significant digit is `1`
    // etc.
}

そのようにすると、おそらくそれらをある種のループに入れたいと思うでしょう。

これを行うためのより良い方法は、次のようにビットごとの andingを使用することです。

if (value & 8 != 0)
    // here you know that the fourth least significant digit (the one representing 8) is 1.
    // do a Google search on bitwise anding to get more information.
于 2012-12-07T01:40:20.540 に答える