C 位運算使用場景之操作整型某一位

2021-09-20 13:23:45 字數 3279 閱讀 7352

前幾天寫了兩篇關於c#位運算的文章

c#位運算基本概念與計算過程

c#位運算實際運用

在文中也提到了位運算的實際作用之一就是合併整型,當時引用了乙個問題:

c# 用兩個short,乙個int32拼成乙個long型,高16位用short,中間32位用int,最低16位用另外乙個short。

答案如下:

高16位shorta、中間32位inta、低16位shortb

longresult=((long)shorta << 48 )+ ((long)inta << 16)+ shortb
根據longresult獲取前16位shorta,中間32位inta,後16位shortb

shorta=(short)(longresult>>48)

inta=(int)((longresult>>16)&0xffffffff)

shortb=(short)(longresult&0xffff)

#1樓 2019-04-30 07:28 pushouli 簡單明瞭,但感覺合併那裡,不應該用加法去算,用|運算子更合適。

#11樓 2019-04-30 18:10 czd890

@ pushouli 用+ 和 | 在這裡效能上應該沒有太大區別。 但是感覺用 | 更能表達意思一些

longresult=(((long)shorta << 48) |((long)inta << 16)) | (long)shortb
1|0=1、1|1=1、0|0=0

其計算結果longresult是一樣的,運算方式不一樣,其計算過程可以看看前面寫的一篇

c#位運算實際運用

如圖:

這篇文章就將記錄兩個知識點:

1.負數的二進位制位表示法

2.位運算如何直接操作int型別某一位

原碼:乙個整數按照絕對值的大小轉換成的二進位制數,稱為原碼

乙個short 16位的整數9的原碼是:

0000	0000	0000	1001
反碼:乙個二進位制數按位取反,所得的二進位制數成為原二進位制數的反碼

取9的二進位制數的反碼,可以使用位邏輯非運算 ~

取反後的16位二進位制

1111	1111	1111	0110
補碼:反碼加1稱為補碼,簡而言之,要得到乙個屬的補碼,先得到這個數的反碼,然後再將反碼加上1,所得數稱為補碼

那麼9的補碼也就是

1111	1111	1111	0110
加上1的結果,如下:

1111	1111	1111	0111
即-9的16位二進位制表示是

1111	1111	1111	0111
如圖:

話不多說,直接明確三點結論:

1.實際開發中,都用的是有符號的int(應該預設強制要求),只有整型有有無符號的特徵,double、decimal,是沒有這種特徵的。

2.無符號數中,所有的位都用於直接表示該值的大小。

3.有符號數中,最高位用於表示正負。

這裡還是簡單地囉嗦幾句關於有符號和無符號的區別,uint32和int32的區別

這裡說的int指的是32位有符號的型別

int32的值範圍是 -2147483648 至2147483647,也就是

-2的31次方到2的31次方-1

符號位表示的意義就在於此,最前面的位表示正負。

-2148483648的32位二進位制是:

1000	0000	0000	0000	0000	0000	0000	0000
2147483647的32位二進位制是:

0111	1111	1111	1111	1111	1111	1111	1111
那麼c#中uint32的最大值是什麼呢?

uint32的範圍是0到2的32次方4294967295,最大值32位二進位制是

1111	1111	1111	1111	1111	1111	1111	1111
所以得出結論無符號只能表示正數,有符號可以表示正負數。

如圖:

前面已經說到,int表示的是有符號的,最高位表示的正負,乙個int有32位,雖然我們可以直接操作這32位,但是如果直接操作明顯會改變資料型別的正負、最大範圍。

這裡寫了乙個泛型的示例,操作整型(int、short、long)的每一位。

/// /// int16\int32\int64型別

///

/// true 1\false 0的集合

public static ienumerablegetintofbitlist(t intval)

return resultlist;

}/// /// 獲取t整型中某一位的值

///

/// 泛型型別包括int\short\long

/// int\short\long

/// 從右到左0-t的總位數

/// true:1\false:0

public static bool getbitvalue(t intval,byte index)

/// /// 設定整型資料中某一位的值

///

/// int\short\long

/// 設定前的值

/// 從右到左0-t的總位數

/// 需要設定的值 true:1\false:0

/// 設定位值後新的整型

public static t setbitvalue(t intval,byte index,bool bitvalue)

else if (inttype == typeof(int16))

else

}

測試截圖:

思考:這個方法能操作負數嗎?

深入理解位運算操作及使用場景

工作中一直沒用過位操作,只有在閱讀一些原始碼的時候會看到使用位運算子 因為直接使用位運算子效率更高 為了更好的閱讀原始碼那就好好學習一下吧,順便把學習的東西記下來。位運算子大致就以下幾種吧。位運算子名稱 符號用法 位求反 expr 左移 expr1 expr2 右移 expr1 expr2 無符號右...

redis使用場景之位操作(大資料處理)

在學習redis的過程了,看到了redis還能用於大資料處理,具體場景如下 原理是 redis內構建乙個足夠長的陣列,每個陣列元素只能是0和1兩個值,然後這個陣列的下標index用來表示我們上面例子裡面的使用者id 必須是數字哈 那麼很顯然,這個幾億長的大陣列就能通過下標和元素值 0和1 來構建乙個...

總結位移運算的規律以及一些使用場景

位移運算 正整數 n 左移運算 相當於 正整數 2的n次冪 正整數 n 右移運算 相當於 正整數 2的n次冪 負整數 n 左移運算 相當於 負整數 2的n次冪 負整數 n 右移運算 相當於 負整數 2的n次冪,如果有餘數則結果再 1,除數大於被除數,結果等於 1 我們在閱讀原始碼的時候會看到有些值明...