C#位运算实际作用之操作整型某一位

1.前言

前几天写了两篇关于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)

评论者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);
            }
        }

测试截图:

思考:这个方法能操作负数吗?

原文地址:https://www.cnblogs.com/zhangmumu/p/10805312.html

时间: 2024-11-08 22:46:54

C#位运算实际作用之操作整型某一位的相关文章

PHP长整型在32位系统中强制转化溢出

CleverCode近期遇到一个PHP项目整形转化问题,mysql有一个字段id是bigint的,里面有长整型,如id = 5147486396.可是php代码因为历史原因却部署在多台机器中,当中A机器32位系统中,B机器64系统中.如今的问题是64系统中页面訪问正常.32位系统中訪问出错了.原因是php整形溢出. 1 A机器演示 1.1 获取A机器系统位数 # getconf LONG_BIT 1.2 整形转化代码 <? php $id = 5147486396; echo '$id:'.$i

以php中的自增自自减运算符操作(整型,浮点型,字符串型,布尔型,空类型)数据

1 // 环境 2 // 3 // php版本 4 // PHP 7.0.33-0+deb9u1 (cli) (built: Dec 7 2018 11:36:49) ( NTS ) 5 // Copyright (c) 1997-2017 The PHP Group 6 // Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies 7 // with Zend OPcache v7.0.33-0+deb9u1, Copyrig

位运算 部分作用

按位与& 作用:1.与0相与迅速清零 2.保留位数 3.与1相与判断奇偶性 按位或| 作用:感觉并没有多大作用 按位异或^  作用:定位反转 (交换值) a=a^b; b=a^b; a=a^b; 左移 :乘以2的n次方 右移 :整除2的n次方

数字位运算操作与算法简单示例

我们对于位运算可能既陌生又熟悉.知道其运算方法运算过程,但不能运用好它. 首先,我们还是回顾一下Java中位运算都包含那些操作: 一.与运算(&) 运算法则:将二进制数进行按位与运算.0&0=0:0&1=0:1&1=1 : 如:0011 & 0010 = 0010: 二.或运算(|) 运算法则:将二进制数进行按位或运算.0|0 =0:1|0 = 1;  1|1=1 如:0011 & 0010 = 0011: 三.异或运算(^) 运算法则:将二进制数进行按位异

位运算的操作与算法

在上一次的博客中,我们实现了使用位操作去实现四则运算.实现整数的加减乘除.这次我们将讨论位运算在算法中的一些妙用. 位运算可以进行的骚操作 在这里我将使用题目进行示例 题1:找出唯一成对的数 1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次.每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一 个算法实现? 这个题目有两个要注意的点 数的范围是1-1000,这个是确定的 不能使用辅助储存空间 只有一个数字g重复 那么

结构体、共用体和位运算

1.C语言结构体的定义和使用 在实际问题中,一组数据往往具有不同的数据类型:例如在学生信息登记表中,姓名为字符型,学号为整型或字符型,年龄为整型,性别为字符型,成绩为整型或实型.因为数据类型不同,显然不能用一个数组来存放. 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.定义结构体的一般形式为: struct 结构体名{ 成员列表 }; 每个成员都是结构体的组成部分,有名字,也有数据类型,形式为: 类型说明符 成员名; 例如用结构体来表示学生信息: struct stu{ c

C#按位运算

在C#中可以对整型运算对象按位进行逻辑运算.按位进行逻辑运算的意义是:依次取被运算对象的每个位,进行逻辑运算,每个位的逻辑运算结果是结果值的每个位.C#支持的位逻辑运算符如表2.9所示. 运算符号 意义 运算对象类型 运算结果类型 对象数 实例 ~ 位逻辑非运算 整型,字符型 整型 1 ~a & 位逻辑与运算 2 a & b | 位逻辑或运算 2 a | b ^ 位逻辑异或运算 2 a ^ b <<  位左移运算 2 a<<4 >>  位右移运算 2 a

Java的位运算

左移位操作 左移位运算的符号为[<<],左移位运算符左面的操作元称作被移位数,右面的操作数称作移位量. 左移位运算是双目运算符,操作元必须是整型类型的数据,其移动过程是:[a << n]运算的过程是通过将a的所有位都左移n位,每左移一个位,左边的最高位上的0或1被移出丢弃,并用0填充右边的低位 注意: 如果a是byte.short或int型数据,总是先计算出n%32的结果m,然后进行a<<m运算 对于long型数据,总是先计算出n%64的结果m,然后进行a <&l

C#位运算讲解与示例

原文:C#位运算讲解与示例[转] 在C#中可以对整型运算对象按位进行逻辑运算.按位进行逻辑运算的意义是:依次取被运算对象的每个位,进行逻辑运算,每个位的逻辑运算结果是结果值的每个位.C#支持的位逻辑运算符如表2.9所示. 运算符号 意义 运算对象类型 运算结果类型 对象数 实例 ~ 位逻辑非运算 整型,字符型 整型 1 ~a & 位逻辑与运算 2 a & b | 位逻辑或运算 2 a | b ^ 位逻辑异或运算 2 a ^ b <<  位左移运算 2 a<<4 &g