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);
}
}

测试截图:



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

有兴趣关注一下我的个人公众号,谢谢

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

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

    CleverCode近期遇到一个PHP项目整形转化问题,mysql有一个字段id是bigint的,里面有长整型,如id = 5147486396.可是php代码因为历史原因却部署在多台机器中,当中A机 ...

  2. 以php中的比较运算符操作整型,浮点型,字符串型,布尔型和空类型

    字符,数字,特殊符号的比较依赖ASC II表,本表原先有127个,后来又扩充了一些,里面包含了奇奇奇怪的符号. ASC II表 https://baike.baidu.com/item/ASCII/3 ...

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

    // 环境 // // php版本 // PHP 7.0.33-0+deb9u1 (cli) (built: Dec 7 2018 11:36:49) ( NTS ) // Copyright (c) ...

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

    // 环境 // // php版本 // PHP 7.0.33-0+deb9u1 (cli) (built: Dec 7 2018 11:36:49) ( NTS ) // Copyright (c) ...

  5. CF1381B Unmerge(位运算的作用)

    题目大意: 给定长度为 \(2n\) 的排列 \(p\) .确定是否存在两个数组 \(a\) 和 \(b\) ,每个数组的长度都为 \(n\) ,并且没有相等的元素,使得 \(p = \operato ...

  6. js浮点型,整型操作方法汇总(进行中)

    浮点数操作方法如下: 1. Math.ceil()用作向上取整.(ceil 天花板) 2. Math.floor()用作向下取整. (floor 地板) (js 中取整底层原理是位运算的取反~运算,运 ...

  7. C 碎片九 预处理&位运算&文件操作

    一.预处理 预处理语句:#开头的语句,在预处理阶段处理预处理语句.包括宏定义.文件包含处理.条件编译 1, 宏定义 1. 不带参数宏定义:#define 标识符  字符串 #define PI 3.1 ...

  8. C#位运算讲解与示例

    首先每一个权限数都是2的N次方数 如:k1=2 ; //添加 k2=4 ; //删除 k3=8; //修改 ... 如此定义功能权限数,当需要组合权限时,就需要对各个所拥有的权限数按位或了. 如: p ...

  9. C入门---位运算

    程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算直接对整数在内存中的二进制位进行操作.由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快. (1),与(&)运算 ...

随机推荐

  1. SQL server 安装成功到使用Sa SQL server验证登录等一系列问题

    使用 Windows 身份验证方式登录 出现错误 无法连接到 本地服务器 解决问题: SQL server配置管理器:服务远程过程调用失败 https://blog.csdn.net/gfjjggg/ ...

  2. LeetCode刷题191203 --回溯算法

    虽然不是每天都刷,但还是不想改标题,(手动狗头 题目及解法来自于力扣(LeetCode),传送门. 算法(78): 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明: ...

  3. java编译报错 错误: 编码GBK的不可映射字符

    解决方法: 1.  javac -encoding UTF-8 .\Test_Sql.java //加上参数指定utf-8 2.改变文件编码 使用 ANSI编码.

  4. varnish实现缓存加速

    varnish实现缓存加速 一.采用varnish为nginx实现缓存加速1.实验环境:(1)一台varnish缓存服务器,一台nginx服务器(2)关闭防火墙和selinux2.配置varnish( ...

  5. Excel上下标如何设置?

    Excel表格怎么设置上下标?Excel上下标设置技巧 在21世纪的我们,平时的工作和学习中,经常会使用到一些专业的文档,比如方程式.数据的公式和科学计数等,其中均会涉及到许多的上下标符号输入以及使用 ...

  6. java.lang.IllegalStateException: getOutputStream() has already been called 解决办法

    因为在使用的时候没有使用@ResponseBody这个注解,所以才会报上面的异常

  7. TKinter容器frame使用

    容器frame使用布局 https://www.cnblogs.com/anita-harbour/p/9315472.html TK控件使用大全 https://blog.csdn.net/rng_ ...

  8. 解决 vscode 中 nuget 插件无法获取包版本的问题

    解决 vscode 中 nuget 插件无法获取包版本的问题 1.问题描述 大概在今年的7月份左右,我忽然发现 NuGet Package Manager 拓展没法正常使用了,只能查询到包: 选完包之 ...

  9. cocos2d-x 新工程的把玩

    创建了cocos的工程以及初步了解了工程的结构之后,可以尝试自己改改代码了 游戏窗口的设置 首先是AppDelegate,找到AppDelegate.cpp中AppDelegate::applicat ...

  10. Python Web(四)

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.Django-forms作用 前端和后端都要校验 前端校验的目的:减少后端的压力 用forms可以同时完成前端 ...