簡體   English   中英

C#從第一個有效位開始獲取uint32的高4位

[英]C# getting upper 4 bits of uint32 starting with first significant bit

我的需求是 - 有一些(實際上偽)隨機數uint32 ,我需要它的4個第一位用第1位表示,而不是0,例如

... 000100101 => 1001

1000 ... 0001 => 1000

... 0001 => 0001

... 0000 => 0000

等我知道我必須使用這樣的東西

uint num = 1157 (some random number)
uint high = num >> offset

問題是 - 我不知道第一位是哪里所以我不能使用>>和常量變量。 有人可以解釋如何找到這個offset嗎?

您可以先計算最高有效位(HSB)然后相應地移位。 你可以這樣:

int hsb = -4;
for(uint cnum = num; cnum != 0; cnum >>= 1, hsb++);
if(hsb < 0) {
    hsb = 0;
}
uint result = num >> hsb;

所以我們首先要檢測最高設置位(或該指數減去4)的索引。 我們通過遞增hsb並將cnumnum的副本)向右移位,直到cnum中沒有設置位cnum

接下來我們確保有這樣的設置位,並且它至少具有索引4(如果沒有,則不執行任何操作)。 結果是原始numhsb向右移動。

如果我在0x123上運行它,我在csharp交互式shell中得到0x9

csharp> uint num = 0x123;
csharp> int hsb = -4;
csharp> for(uint cnum = num; cnum != 0; cnum >>= 1, hsb++);
csharp> if(hsb < 0) {
      >     hsb = 0;
      > }
csharp> uint result = num >> hsb;
csharp> result
9

0x123是二進制的0001 0010 0011 所以:

0001 0010 0011
   1 001

10019

確定最重要的非零位的位置與計算基數2的對數相同。在現代CPU上有快速執行此操作的“位移技巧”:

int GetLog2Plus1(uint value)
{
    value |= value >> 1;
    value |= value >> 2;
    value |= value >> 4;
    value |= value >> 8;
    value |= value >> 16;
    value -= value >> 1 & 0x55555555;
    value = (value >> 2 & 0x33333333) + (value & 0x33333333);
    value = (value >> 4) + value & 0x0F0F0F0F;
    value += value >> 8;
    value += value >> 16;
    value &= 0x0000003F;
    return (int) value;
}

這將返回0到32之間的數字:

Value                                      | Log2 + 1
-------------------------------------------+---------
0b0000_0000_0000_0000_0000_0000_0000_0000U |        0
0b0000_0000_0000_0000_0000_0000_0000_0001U |        1
0b0000_0000_0000_0000_0000_0000_0000_0010U |        2
0b0000_0000_0000_0000_0000_0000_0000_0011U |        2
0b0000_0000_0000_0000_0000_0000_0000_0100U |        3
...
0b0111_1111_1111_1111_1111_1111_1111_1111U |       31
0b1000_0000_0000_0000_0000_0000_0000_0000U |       32
0b1000_0000_0000_0000_0000_0000_0000_0001U |       32
...                                        |
0b1111_1111_1111_1111_1111_1111_1111_1111U |       32

(Math nitpickers會注意到0的對數是未定義的。但是,我希望上面的表格能夠說明如何處理這個問題並對這個問題有意義。)

然后,如果值小於8(其中log2 + 1 <4),則可以計算最重要的非零位,同時考慮您需要4個最低有效位:

var log2Plus1 = GetLog2Plus1(value);
var bitsToShift = Math.Max(log2Plus1 - 4, 0);
var upper4Bits = value >> bitsToShift;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM