【位运算进阶之----右移(>>)】

news2024/11/22 10:33:48

😄嘻嘻,朋友们,大家好!昨天我们学习了左移,今天我们来谈谈右移>>。


⭐️简单来说,右移就是将一个数二进制表达整体向右移动,也就是去掉一个数的二进制表达的末位,右移一位就去掉一位,右移两位就去掉两位。一般情况下右移就是除以2的幂并向下取整。

下面就让我们来详细看看吧!

在这里插入图片描述


文章目录

  • 一、基础知识
    • 1️⃣ 右移的二进制表示:
    • 2️⃣ 右移的执行结果:
    • 3️⃣ 对负数右移:-x>>y=-⌈(x>>y)⌉(不建议用)
      • 1. -9>>1
      • 2. ((unsigned int)-9) >> 2
    • 4️⃣ 右移负数位:
  • 二、拓展应用:
    • 1. 去除低k位:
    • 2. 取第k位的值:
  • 三、写在后面的话:


一、基础知识

✨右移运算符是一个二元运算符,右移操作是也一种位操作,用来将一个数的二进制表达所有位向右移动指定的位数

✨我们知道,无符号整数都是非负数,所以负数只出现在有符号整数中。(所以我们这里可以不分有符号整数和无符号整数):

  • 对于正数直接右移(左侧添0,可视为不添)
  • 对于负数右移后左侧添1;0你懂的

1️⃣ 右移的二进制表示:

✨x>>y 表示将x的二进制表达向右移动y位(其中x和y都是整数)。
如:1001 >> 2 ----> 10 (直接去掉后两位)


2️⃣ 右移的执行结果:

✨右移操作相当于将一个数除以2的n次方
x>>y <=> [ x 2 y \frac {x}{2^y} 2yx] ,方括号一般认为是向下取整。咦?不是常说右移是除以2,左移是乘以2吗,你这怎么还向下取整了呢?
在这里插入图片描述
👉因为不是所有的数都能被2整除,所以根据C语言右移的规则,应当向下取整。(C语言除法结果是正数则向下取整,结果为负数则向零取整)
在这里插入图片描述

  • 所以上面的1001>>2 = [ 9 2 2 \frac {9}{2^2} 229] = [ 9 4 \frac {9}{4} 49] = 2(向下取整)

代码如下:

#include<stdio.h>

int main(void)
{
	int a = 0b1001;
	unsigned int b = a ;
	printf("%d\n", a>>2);
	printf("%u\n", b>>2);
	
	return 0;
}

执行结果如下:

在这里插入图片描述
可以看出结果是9/4=2;
下面我们继续增大右移的位数:

#include<stdio.h>

int main(void)
{
	int a = 0b1001;//9
	unsigned int b = a ;
	printf("%d\n", a>>4);
	printf("%u\n", b>>4);
	
	return 0;
}

在这里插入图片描述
可以看出9/16=0,没什么问题。

  • 当然,这里也可以从补码(移位)的角度来解释。9的二进制表达一共4位有效,向右移动4位后显然是0。

3️⃣ 对负数右移:-x>>y=-⌈(x>>y)⌉(不建议用)

注:-x>>y并不等于-(x>>y)

如:-9>>1 是多少呢?相信你心中已经有答案了,请看下图!

#include<stdio.h>

int main(void)
{
	int a = -9;
	unsigned int b = a ;
	printf("%d\n", a >> 1);//	-9>>1
	printf("%d\n", a / 2);//	-9/2
	printf("%d\n", a>>2);//		-9>>2
	printf("%d\n", a >> 3);//	-9>>3

	printf("%u\n", b>>2);//		(unsigned int )-9>>2
	return 0;
}

执行结果如下:
在这里插入图片描述

我们先来看a,a是一个有符号整数-9,现在对其右移。

1. -9>>1

  • (1)值的角度:
    -9>>1 = [-9/2] = [-4.5] = -5 (向下取整),但-(9>>1)=-([9/2])=-4
    注意:这里千万要和-9/2 = -4区分开来!因为在C语言中,对于负数的取整通常是向零取整(向上取整)。也就是说,负数会被取整为最接近且大于等于它的整数。
    如:(int)(-3.9) = -3 ;(int)(-2.1) = -2;

对应的符合见下图,左面是向下取整,右面是向上取整:
在这里插入图片描述
下面是它们的图像:

❤️向下取整(高斯函数):
在这里插入图片描述
❤️向上取整:
在这里插入图片描述
这里我就不展开讨论了,以后有机会再深入去了解其二者的相关知识。

  • (2)补码的角度:
    • 9的补码是:00000000 00000000 0000000 00001001
    • -9的补码是:11111111 11111111 11111111 11110110 + 1-->11111111 11111111 11111111 11110111
    • -9的补码右移一位:11111111 11111111 11111111 11111011(左侧补1)
    • 转换成机器数(原码):10000000 00000000 00000000 00000100+1-->10000000 00000000 00000000 00000101 = -5

😄综上我们得到了-x>>y = -⌈(x>>y)⌉ = -(⌈ x 2 y \frac {x}{2^y} 2yx⌉),注意,此处是向上取整,但计算机中默认正整数除法是向下取整,所以你可能要用ceil函数自己处理。

-9>>2,-9>>3与上面的推理过程类似,此处不再赘述!


2. ((unsigned int)-9) >> 2

  • 现在,就让我们来看看上图的最后一个输出,为什么是1073741821呢?

在这里插入图片描述
✨首先,b的类型是unsigned int ,无符号整型,也就是都是非负的。现在我们执行第一个语句:b=a , 将-9赋值给一个无符号整型,b的值将会变成多少呢?这里我们借助昨天的图来进行求解:👇
在这里插入图片描述
✨如何求b的值,言下之意就是让我们从0开始往左数9个数,可以轻松得到b的值是2 ^ 32-9,也就是4294967296-9=4294967287
✨现在,我们得到了((unsigned int)-9) >> 2 <=> 4294967287>>2,下面从两个方面进行求解:

  • (1)值的角度:然后另b除以4并向下取整,即[4294967287/4]=4294967287/4=1073741821
  • (2)移位的角度:
    1. 因为2 ^ 32-1的二进制表达是:11111111 11111111 11111111 11111111
    2. 所以2 ^ 32-9的二进制表达可以写为:11111111 11111111 11111111 11111111-00000000 00000000 00000000 00001000=11111111 11111111 11111111 11110111
    3. 现对其右移两位:00111111 11111111 11111111 11111101,然后将其以十进制的形式输出即可。

验证一下输出:

#include<stdio.h>

int main(void)
{
	int b = 0b00111111111111111111111111111101;
	printf("%d", b);
	return 0;
}

执行结果如下:
在这里插入图片描述
执行结果正确,证明上述解法可行。


4️⃣ 右移负数位:

✨昨天我们了解了左移负数位的情况,发现那是未定义的行为,现在我们来看看右移负数位又会如何?let's go!!!
在这里插入图片描述
我们先来看一段代码:

#include<stdio.h>

int main(void)
{
	int a = 9;
	printf("%d\n", a >>  0);
	printf("%d\n", a >> -1);
	printf("%d\n", a >> -2);
	printf("%d\n", a >> -3);
 	return 0;
}

执行结果如下:
在这里插入图片描述

💔咦❓这个输出有点意思,到底是怎么回事呢❓右移负数位竟然没有报错,那就是合理的❓既然合理,那为啥会出现这种结果呢❓按照我们以往的思维,右移-1位就是左移1位啊❗️结果不应该是18吗,怎么不对呢❓阁下莫急,我们接着往下看:

#include<stdio.h>

int main(void)
{
	int a = 9;
	printf("%d\n", a >>  0);
	printf("%d\n", a >> -1);
	printf("%d\n", a >> -2);
	printf("%d\n", a >> -3);
	printf("***\n");
	printf("%d\n", a >> -30);
	printf("%d\n", a >> -31);
	printf("%d\n", a >> -32);
	printf("%d\n", a >> -33);
	printf("%d\n", a >> -34);
	printf("%d\n", a >> -35);
	return 0;
}

执行效果如下:
在这里插入图片描述
💔咦?下面这个结果也有点出乎意料啊!9>>-30结果是2❗️9>>-32结果是9❗️相信如果你对数字比较敏感的话,应该已经发现了右移负数位的规律。当然,如果没有发现也不用着急,我们继续往下看:

#include<stdio.h>

int main(void)
{
	int a = 9;
	printf("%d\n", a >>  0);
	printf("%d\n", a >> -1);
	printf("%d\n", a >> -2);
	printf("%d\n", a >> -3);
	printf("***\n");
	printf("%d\n", a >> -30);
	printf("%d\n", a >> -31);
	printf("%d\n", a >> -32);
	printf("%d\n", a >> -33);
	printf("%d\n", a >> -34);
	printf("%d\n", a >> -35);
	printf("***\n");
	printf("%d\n", a >> -62);
	printf("%d\n", a >> -63);
	printf("%d\n", a >> -64);
	printf("%d\n", a >> -65);
	printf("%d\n", a >> -66);
	printf("%d\n", a >> -67);
	return 0;
}

在这里插入图片描述
❤️通过第三个代码我们可以看出:
🌟右移-32位的倍数的时候和右移0位时类似,都是其本身;
🌟右移-30位和右移-62位类似,都是2,那2又有什么特殊之处呢?我们来看看它们的补码:

  • 9的原(补)码是:00000000 00000000 00000000 00001001
  • 2的原(补)码是:00000000 00000000 00000000 00000010

可以看出,9>>2 = 2,且32-(abs(-30)%32)=232- (abs(-62)%32)=2

🌟右移-31位和右移-63位类似,都是4

  • 4的原(补)码是:00000000 00000000 00000000 00000100

我们知道9>>1 = 4,且32-(abs(-31)%32)=132- (abs(-63)%32)=1

所以,经过上述的推导我们可以得出右移负数位的计算公式:
若记右移n位(n为负数),并记结果为result,则
result=32-(abs(n)%32)

(此为博主自己总结的结论,如有错误还请指正,如需引用还请注明出处)

当然,右移负数位在平常很少用到(一般都在一定范围内左移或右移,别自己给自己找麻烦)。


二、拓展应用:

✨下面的第k位均为从右往左第k位(从第0位开始数),如果习惯按第1位开始,则可令k=k+1;

1. 去除低k位:

给定一个数x,将其低k位去除后再输出。
方法:直接右移k位即可,x>>k

2. 取第k位的值:

二进制表达只有0或1,所以第k位要么是0,要么是1。
方法:将x右移k位后 和1位于 or 和0位或
(x>>k)&1 or (x>>k)|0

  • 除此之外,还有其他的一些操作,都可以通过位运算的相关定义得出,此处不再赘述!

三、写在后面的话:

🔥自从chatgpt等大语言模型出现之后,立刻就有了相当广泛的应用。不论是商用还是民用,像是平常询问零碎的知识点,聊天,写代码等等,都有了其一席之地。不可否认,它们的确很强大。但随着其进一步发展,就拿CSDN平台来说,无论是问答还是写博客,都或多或少地存在着它们的影子。

🔥先说写博客方面,过分依赖于gpt写的博客和人写的博客其实差异还是蛮大的,因为前者写的大都比较生硬,基本以大片大片的概念为主,缺乏和观者的互动;并且其所述的知识也不一定都是正确的,所以我想说什么,你懂的。

🔥再说问答方面,我无法忍受一个外行人完全借助gpt来回答各行各业的问题,你回答对了我不说什么,但你完全借其所答,拿着错误的答案去回复别人,这既是一种对问者的不尊敬,也是对自己行为的不负责。我认为,它应该成为一种提升自己能力的工具,而不是将其信奉为教条,它可以用来验证我们的想法,也可以帮我们打开思路,但唯独不能代替我们。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


好了,今天的讲解就到这里了,相信你也是收获满满吧!接下来我将会开专栏讲解数据结构和算法Python等相关知识,希望对你能有所帮助!


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/938517.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

apex和pl/sql学习记录2

验证后过程函数代码插眼儿 -- 登录后验证过程3 create or replace PROCEDURE TEST_USER_WXX3_PRO ASV_USER_ID NUMBER(20);V_ROLE_ID NUMBER(20);V_PERM_ID NUMBER(20);V_DEPT_ID NUMBER(20);V_USER_NAME NVARCHAR2(64);V_JOB_NUMBER NVARCHAR2(32);V_M…

破除“中台化”误区,两大新原则考核中后台

近年来&#xff0c;“中台化”已成为许多企业追求的目标&#xff0c;旨在通过打通前后台数据和业务流程&#xff0c;提升运营效率和创新能力。然而&#xff0c;在实施过程中&#xff0c;一些误解可能导致“中台化”未能如预期般发挥作用。本文将探讨这些误解&#xff0c;并提出…

Exploring Unreal Engine New Free Archviz Explorer Project 视频笔记

链接&#xff1a; https://www.bilibili.com/video/BV1Q34y1Z7he/ 场景中没有太阳&#xff0c;也没有定向光 该蓝图用来控制光线的显示 删除这个蓝图 添加这个蓝图 顶部会出现时间滑块 该项目还有扩展插件&#xff0c;用户可以自由下载 它是由一个8k的卫星图做的地形底图 …

『PyQt5-基础篇』| 05 Qt Designer保存的.ui文件如何生成.py文件?

05 Qt Designer保存的.ui文件如何生成.py文件? 1 使用Qt Designer设计一个简单的界面2 UI文件转PY文件2.1 方法一:直接使用命令2.2 方法二:直接调用PyUIC5工具3 运行转换后的py文件.ui文件是用Qt Designer设计的界面保存后的文件;保存后我们需要把这个文件转换成.py 文件,…

为什么要进行管网水位监测,管网水位监测的作用是什么

管网水位监测是城市排水系统管理的重要手段&#xff0c;对于保障城市排水设施安全运行和提升城市管理水平具有重要意义。通过对排水管网的水位进行实时监测和分析&#xff0c;能够及时发现问题并采取措施&#xff0c;提高排水系统的运行效率和管理水平。本文将详细介绍为什么要…

情感书单视频做怎么制作?几个步骤轻松生成

在当今数字化的时代&#xff0c;制作情感书单视频已经成为了一种流行的方式来分享个人阅读心得。然而&#xff0c;制作这样的视频并不是一件简单的事情。本文将介绍制作情感书单视频的步骤&#xff0c;并讨论需要注意的事项。 准备工作 在制作情感书单视频之前&#xff0c;最好…

空时自适应处理用于机载雷达——额外的性能结果(Matla代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

③matlab向量和矩阵

目录 手动输入数组 创建等间距向量 数组创建函数 手动输入数组 1.背景 单个称为标量的数值实际上是一个 11 数组&#xff0c;也即它包含 1 行 1 列。 任务 创建一个名为 x 并且值为 4 的变量。 2.您可以使用方括号创建包含多个元素的数组。 x [3 5] x 3 5 任务 …

馈纸式扫描仪贵到让人咋舌,您知道原因吗?

嘿&#xff0c;话说到馈纸式扫描仪&#xff0c;给它一个字就是&#xff1a;“贵”&#xff01;我在某宝上查了一下&#xff0c;最便宜的都快500元了&#xff0c;某东上更是贵得让人咋舌&#xff0c;动不动就几千上万&#xff0c;甚至几十万的都有&#xff0c;而一般的平板扫描仪…

Redis的数据结构与单线程架构

"飞吧&#xff0c;去寻觅红色的流星" Redis中的五种数据结构和编码 Redis是一种通过键值对关系存储数据的软件&#xff0c;在前一篇中&#xff0c;我们可以使用type命令实际返回当前键所对应的数据结构类型&#xff0c;例如: String\list\hash\set等等。 但…

如何在钉钉内跳转自己的网页链接

1.跳转网页转码(工具地址) 原网页:https://www.baidu.com/ 转码后:https%3A%2F%2Fwww.baidu.com%2F 2:地址拼接(官方跳转地址:dingtalk://dingtalkclient/page/link?urlURL&pc_slidetrue) 替换URL: dingtalk://dingtalkclient/page/link?urlhttps%3A%2F%2Fwww.baidu.co…

路径规划 | 图解Theta*算法(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 A*算法的局限性2 Theta*算法原理图解3 Bresenham视线法4 算法仿真测试4.1 算法流程图4.2 ROS C 实现4.3 Python实现4.4 Matlab实现 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全…

为什么这3类人,一定要选择无代码开发?

一个人也能开发出一个软件&#xff1f;这或许难以想象的&#xff0c;但无代码技术的问世&#xff0c;让这一切都成为现实。 可能很多人对“无代码”还是不太熟悉&#xff0c;但大家一定都听说过“码农”这个词&#xff0c;而无代码开发技术的出现&#xff0c;可以让我们摆脱这…

Node.js @zurmokeeper/exceljs 如何快速导出多表头的excel文件

Node.js 如何快速导出嵌套列&#xff08;多表头&#xff09;的excel文件。效果图如下&#xff1a; 1&#xff1a;使用 zurmokeeper/exceljs&#xff0c; V4.4.1以上 安装&#xff1a; npm i zurmokeeper/exceljs 2: 有一个 worksheet.makeColumns 方法&#xff0c;API文档&am…

第六章:数据结构与算法-par1:典型数据结构

文章目录 一、典型数据结构介绍1.1 基本概念和术语1、基本数据概念2、抽象数据类型3、算法4、算法复杂度5、数据结构 二、数据的存储结构2.1 线性结构1、线性表&#xff08;一般线性表&#xff09;2、栈和队列&#xff08;受限线性表&#xff09;1) 栈 Stack2&#xff09; 队列…

怎么在线制作思维导图?分享几个好用的方法和注意事项

思维导图是一种非常有用的工具&#xff0c;它可以帮助我们整理和梳理思路&#xff0c;提高学习和工作效率。现在&#xff0c;越来越多的人开始使用在线工具来制作思维导图&#xff0c;因为它们不仅方便易用&#xff0c;而且可以随时随地进行编辑和共享。本文将介绍几个好用的在…

生产环境部署与协同开发 Git

目录 一、前言——Git概述 1.1 Git是什么 1.2 为什么要使用Git 什么是版本控制系统 1.3 Git和SVN对比 SVN集中式 Git分布式 1.4 Git工作流程 四个工作区域 工作流程 1.5 Git下载安装 1.6 环境配置 设置用户信息 查看配置信息 二、git基础 2.1 本地初始化仓库 ​编辑…

C语言二——C++编写一段代码,求一元三次方程的根

这段代码是用来解决一元三次方程的程序。它使用了复数运算&#xff0c;并根据判别式的值进行不同分支的处理&#xff0c;输出方程的根。 您可以在程序中输入一元三次方程的系数a、b、c和d&#xff0c;然后调用solve_cubic_equation函数进行求解。函数会根据判别式的值进行不同…

云计算和Docker分别适用场景

在大规模网络爬虫系统中&#xff0c;通过使用云计算和Docker技术&#xff0c;可以实现大规模网络爬虫系统的高效架构设计和部署。这种架构能够提供可扩展性、高可用性和灵活性&#xff0c;为爬虫系统的运行和管理带来便利。 云计算和Docker在大规模网络爬虫系统中有不同的业务…

【C语言】用函数递归的方法解决汉诺塔问题

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn&#x1f493; ⏩专栏分类&#xff1a;C语言 &#x1f69a;代码仓库&#xff1a;小小unicorn的学习足迹&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 汉诺塔 1.问题起源:2.汉诺塔游戏规…