C#位運算實際作用之操作整型某一位


c#位運算系列

1.前言

在文中也提到了位運算的實際作用之一就是合並整型,當時引用了一個問題:
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)

評論者pushouli、czd890 評論到,合並這個long類型的結果是使用加法計算,可以使用位邏輯或運算,想了想確實使用| 位邏輯或運算也是可以解決問題的,能夠實現相互轉換。

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類型某一位

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

原碼:一個整數按照絕對值的大小轉換成的二進制數,稱為原碼
一個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

如圖:
在這里插入圖片描述

3.c#Int有符號的和無符號的區別

話不多說,直接明確三點結論:
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

所以得出結論無符號只能表示正數,有符號可以表示正負數。
如圖:
在這里插入圖片描述

4.c#Int如何直接操作每一位

前面已經說到,Int表示的是有符號的,最高位表示的正負,一個Int有32位,雖然我們可以直接操作這32位,但是如果直接操作明顯會改變數據類型的正負、最大范圍。
這里寫了一個泛型的示例,操作整型(int、short、long)的每一位。

     /// <summary>
        /// Int16\Int32\Int64類型
        /// </summary>
        /// <returns>true 1\false 0的集合</returns>
        public static IEnumerable<bool> GetIntOfBitList<T>(T  intVal)
        {
            Type intType = intVal.GetType();
            byte bitlength = 0;
            if (intType == typeof(Int32))
                bitlength = 32;
            else if (intType == typeof(Int16))
                bitlength = 16;
            else if (intType == typeof(Int64))
                bitlength = 64;
            else
                throw new ArgumentException("必須是整型");

            object intOject = (object)intVal;
            var resultList = new List<bool>(bitlength);
            for (var i = 0; i < bitlength; i++)
            {
                var temoIntBit = 1 << i;
                if (intType == typeof(Int32))
                    resultList.Add((((Int32)intOject) & temoIntBit) == temoIntBit);
                if (intType == typeof(Int16))
                    resultList.Add((((Int16)intOject) & temoIntBit) == temoIntBit);
                if (intType == typeof(Int64))
                    resultList.Add((((Int64)intOject) & temoIntBit) == temoIntBit);
            }
            return resultList;
        }
        /// <summary>
        /// 獲取T整型中某一位的值
        /// </summary>
        /// <typeparam name="T">泛型類型包括int\short\long</typeparam>
        /// <param name="intVal">int\short\long</param>
        /// <param name="index">從右到左0-T的總位數</param>
        /// <returns>true:1\false:0</returns>
        public static bool GetBitValue<T>(T  intVal,byte index)
        {
            Type intType = intVal.GetType();
            byte bitlength = 0;
            if (intType == typeof(Int32))
                bitlength = 32;
            else if (intType == typeof(Int16))
                bitlength = 16;
            else if (intType == typeof(Int64))
                bitlength = 64;
            else
                throw new ArgumentException("必須是整型");

            if (index > bitlength-1 || index < 1)
                throw new ArgumentOutOfRangeException("index");

            object intOject = (object)intVal;
            var tempBit = 1 << index;

            if (intType == typeof(Int32))
                return (((int)intOject) & tempBit) == tempBit;
            else if (intType == typeof(Int16))
                return (((Int16)intOject) & tempBit) == tempBit;
            else
                return (((Int64)intOject) & tempBit) == tempBit;
        }
        /// <summary>
        /// 設置整型數據中某一位的值
        /// </summary>
        /// <typeparam name="T">int\short\long</typeparam>
        /// <param name="intVal">設置前的值</param>
        /// <param name="index">從右到左0-T的總位數</param>
        /// <param name="bitValue">需要設置的值 true:1\false:0</param>
        /// <returns>設置位值后新的整型</returns>
        public static T SetBitValue<T>(T intVal,byte index,bool bitValue)
        {
            Type intType = intVal.GetType();
            byte bitlength = 0;
            if (intType == typeof(Int32))
                bitlength = 32;
            else if (intType == typeof(Int16))
                bitlength = 16;
            else if (intType == typeof(Int64))
                bitlength = 64;
            else
                throw new ArgumentException("必須是整型");
            //不能去設置最高位
            if (index >= bitlength-1 || index < 1)
                throw new ArgumentOutOfRangeException("index");

            object intOject = (object)intVal;
            var tempBit = 1 << index;

            if (intType == typeof(Int32))
            {
                int tempInt = (int)intOject;
                return (T)((bitValue ? (tempInt | tempBit) : (tempInt & ~tempBit)) as Object);
            }
            else if (intType == typeof(Int16))
            {
                Int16 tempInt = (Int16)intOject;
                return (T)((bitValue ? (tempInt | tempBit) : (tempInt & ~tempBit)) as Object);
            }
            else
            {
                Int64 tempInt = (Int64)intOject;
                return (T)((bitValue ? (tempInt | tempBit) : (tempInt & ~tempBit)) as Object);
            }
        }

測試截圖:
在這里插入圖片描述
思考:這個方法能操作負數嗎?
有興趣關注一下我的個人公眾號,謝謝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM