原码、补码以及正数/负数的左移和右移

原码、补码以及正数/负数的左移和右移文章目录一 原码和补码 1 1 原码表示法 1 2 补码表示法二 C 正数 负数的左移和右移 2 1 正数的左移和右移 2 2 负数的左移和右移 2 3 扩展 对正负数都适用 下面以正数为例 一 原码和补码对数据用 n 位二进制数编码后 机器数 X 表示为 X XnXn 1Xn 2 X2X1X X nX n 1 X n 2 X 2 X 1 X Xn Xn 1 Xn 2 X2 X1

一 、原码和补码

对数据用n位二进制数编码后,机器数X表示为: X = X n X n − 1 X n − 2 . . . X 2 X 1 X=X_nX_{n-1}X_{n-2}…X_{2}X_{1} X=XnXn1Xn2...X2X1

1.1 原码表示法

1)原码的定义:一个数的原码表示由符号位直接后跟数值位构成,因此,也称“符号-数值 (sign and magnitude)“表示法。原码表示法中,正数和负数的编码表示仅符号位不同,数值部分完全相同。

2)原码编码规则如下:

  • 当X为正数时, X n = 0 X_n=0 Xn=0,后面的位数表示数值。
  • 当X为负数时, X n = 1 X_n=1 Xn=1,后面的位数表示数值。

3)原码0有两种表示形式:

  • [ + 0 ] 原 = 000 … 0 [+0]_原 = 000…0 [+0]=0000
  • [ − 0 ] 原 = 100 … 0 [-0]_原=100…0 [0]=1000

4)原码表示范围(对于n位二进制编码): − ( 2 n − 1 − 1 ) -(2^{n-1}-1) (2n11) ( 2 n − 1 − 1 ) (2^{n-1}-1) (2n11)

1.2 补码表示法

1)补码的定义:正数的补码是它本身;负数的补码等于模与该负数绝对值之差。(对于n位二进制编码,它的模是 2 n 2^n 2n

2)补码0的表示形式:

  • [ + 0 ] 补 = [ − 0 ] 补 = 2 n + ( 士 0 ) = 100 … 0 = 00 … 0 ( m o d 2 n ) [+0]_补=[-0]_补=2^n+(士0)=100…0=00…0(mod 2^n) [+0]=[0]=2n+(0)=1000=000(mod2n)

从上述结果可知,补码0的表示是唯一的。这带来了以下两个方面的好处:一是减少了+0和-0之间的转换。二是少占用一个编码表示,使补码比原码能多表示一个最小负数。

3)求一个数的补码(在原码的基础上):

  • 对于正数,符号位取0,数值部分不变。
  • 对于负数,符号位取1,对数值部分“各位取反,末尾加1”。

4)补码表示范围(对于n位二进制编码): − ( 2 n − 1 ) -(2^{n-1}) (2n1) ( 2 n − 1 − 1 ) (2^{n-1}-1) (2n11)

二、C++正数/负数的左移和右移

在机器中,数的二进制码的表示形式是补码。

2.1 正数的左移和右移

正数的移位比较简单,左移是在二进制数的右边补0,右移是在二进制数的左边补0(因为符号位是0)。

#include <iostream> using namespace std; int main() { 
     int a = 3; // 0000 0000 0000 0000 0000 0000 0000 0011 cout << (a << 1) << endl; // 0000 0000 0000 0000 0000 0000 0000 0110:6 cout << (a >> 1) << endl; // 0000 0000 0000 0000 0000 0000 0000 0001:1 return 0; } 

2.2 负数的左移和右移

1)负数的左移:左移是在二进制数的右边补0。一个负数在左移的过程中会出现有正有负的情况,因为最高的符号位可能变成0,所以要清楚负数左移不会特殊处理符号位。如果一直左移,最终会变成0。

#include <iostream> using namespace std; int main() { 
     int a = -3; // 1111 1111 1111 1111 1111 1111 1111 1101 cout << (a << 1) << endl; // 1111 1111 1111 1111 1111 1111 1111 1010:-6 cout << (a << 30) << endl; // 0100 0000 0000 0000 0000 0000 0000 0000:2^30= cout << ((a << 30) << 2) << endl; // 0000 0000 0000 0000 0000 0000 0000 0000:0 return 0; } 

2)负数的右移:右移是在二进制数的左边补1(因为符号位是1)。如果一直右移,最终会变成-1,即二进制数变成全1,而全1在补码中就表示为-1。并且后面不管继续右移多少位,结果还是-1。

#include <iostream> using namespace std; int main() { 
     int a = -3; // 1111 1111 1111 1111 1111 1111 1111 1101 cout << (a >> 1) << endl; // 1111 1111 1111 1111 1111 1111 1111 1110:-2 cout << (a >> 2) << endl; // 1111 1111 1111 1111 1111 1111 1111 1111:-1 cout << (a >> 3) << endl; // 1111 1111 1111 1111 1111 1111 1111 1111:-1 return 0; } 

2.3 扩展(对正负数都适用,下面以正数为例)

1)移位里一个比较特殊的情况是当移位的位数等于或超过该数值类型的最大位数时,编译器会用移位的位数去模该类型的最大位数,然后按余数进行移位,如:

#include <iostream> using namespace std; int main() { 
     // 这里int类型是32位 int a = 3; cout << (a << 33) << endl; // 33 % 32 = 1,左移1位,a变成6 cout << (a >> 33) << endl; // 33 % 32 = 1,右移1位,a变成1 return 0; } 

2)另外注意,如果移位的位数没有等于或超过该数值类型的最大位数,即使移位相同的位数(通过几次移位),结果也是不一样的,如:

#include <iostream> using namespace std; int main() { 
     int a = 3; a = a << 31; cout << (a << 2) << endl; // 结果为:0 return 0; } 

这里和1)中一样总共左移了33位,但结果是0,而不是6,要注意这一点。

3)移位负数(即移位的位数是负数)

移位负数的计算是,用被移动数的数值类型的最大位数和该负数相加,再移动所得结果即可。(已测试过,不是用负数的数值类型的最大位数,而是用被移动数的)

例如:左移-31,因为a用int类型存储,而我这里int类型是32位存储,所以32+(-31)=1,即左移1位。

#include <iostream> using namespace std; int main() { 
     int a = 1; cout << (a << -31) << endl; // 32+(-31)=1,即左移1位。结果为:2 return 0; } 

注:移位负数这里我查了一些资料并测试过,但还不能肯定是这样计算,如有错,望指正。


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232110.html原文链接:https://javaforall.net

(0)
上一篇 2025年11月1日 上午11:01
下一篇 2025年11月1日 上午11:22


相关推荐

  • nginx ssl配置详解_nginx实现内外网同时访问

    nginx ssl配置详解_nginx实现内外网同时访问1、nginx.conf添加includeproxy.conf2、配置proxy.confserver{ listen80;listen443ssl; server_name域名1; indexindex.jspindex.htmlindex.htmlindex.shtml; ssl_certificate域名1.com.pem;#ssl证书路径 ssl_certificate_key域名1.com.key;.

    2022年10月2日
    4
  • 单片机入门知识

    作为一个大三老狗,才开始单片机入门,晚是晚了点,但是由于知识体系比大一大二稍加完善,所以看问题也相对于更加全面,所以写下学习笔记作为分享,当然,知识水平有限,希望大神们能够给出修改意见。学习参考书:51单片机C语言教程(郭天祥)学习芯片:STC89C52第一篇单片机入门知识:基础知识整合:单片机概念:单片机就是指的一块集成芯片,上面集成了微处理器、存储器及各种输入/输出接口。单片

    2022年4月4日
    46
  • OpenClaw 部署避坑清单:环境配置与多模型接入实战

    OpenClaw 部署避坑清单:环境配置与多模型接入实战

    2026年3月16日
    2
  • linux下rsync命令,Linux 命令之rsync命令详解

    linux下rsync命令,Linux 命令之rsync命令详解rsync 命令 rsync 命令是一个远程数据同步工具 可通过 LAN WAN 快速同步多台主机间的文件 rsync 使用所谓的 rsync 算法 来使本地和远程两个主机之间的文件达到同步 这个算法只传送两个文件的不同部分 而不是每次都整份传送 因此速度相当快 rsync 是一个功能非常强大的工具 其命令也有很多功能特色选项 我们下面就对它的选项一一进行分析说明 语法 rsync OPTION SRC

    2026年3月26日
    2
  • 图标变成了一张白纸_win10桌面图标变白纸

    图标变成了一张白纸_win10桌面图标变白纸win+R输入ie4uinit-show

    2022年10月19日
    6
  • 业务流程引擎_业务流程管理

    业务流程引擎_业务流程管理一般的时候,我们都采用编程式开发,编程式开发的好处非常明显:直接、高效、自由,当然其缺点也是有的,与其优点刚好相对,因为直接,所以有些变化都要进行代码上的修改;因为高效,所以一旦出问题,导致的结果也比较严重,因为自由,所以带来的修改风险也比较大。  这也就是许多大的公司都在进行流程化开发的重要原因之一,比如:上海普元,Livebos,Justep,还有许许多多知名不知名的公司都有类似的流程化开发

    2026年4月13日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号