Python示例——负数的位运算
平时在coding的时候虽然会遇到位运算但一般也都是正数的位运算,今天突然见到了使用负数的位运算,对此十分好奇和困惑,为此做了下了解,于是有了此文。
给出一些位运算的例子:

其中,正数的位运算是最为常见的,如:
1<<0
1<<1
1<<2
(1<<0)&2
(1<<1)&2
(1<<2)&2
但是对于负数的位运算还是没有见过的,如:
(1<<0)&-2
(1<<1)&-2
(1<<2)&-2
搜索了下网上的资料,还真有这方面的解释:
答案就是:
其实,负数在进行位运算时是以补码形式参与计算的。
由 https://baike.baidu.com/item/%E8%A1%A5%E7%A0%81/6854613?fr=aladdin 可知:
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理
由 http://c.biancheng.net/view/290.html 可知:
原码:用最高位表示符号位,其余位表示数值位的编码称为原码。其中,正数的符号位为 0,负数的符号位为 1。
正数的原码、反码、补码均相同。
负数的反码:把原码的符号位保持不变,数值位逐位取反,即可得原码的反码。
负数的补码:在反码的基础上加 1 即得该原码的补码。
===============================
扩展的知识:
既然在编程语言中负数是以反码的形式参与计算的,那么负数是以几个字节的形式来表示的呢,不然他的反码形式怎么写呢?
从上面的问题我们又引出了一个新问题,那就是python中int类型数据是几个字节的?
计算机编程基础好的人应该会知道其实在编程语言中int类型字节数不仅与编程语言有关,也与硬件环境有关,比如:C语言的int类型字节数就受计算机硬件平台所影响。但是,在JAVA语言中不论在什么硬件平台上int类型的字节数都是不变的。有关int字节数这个问题,这些年很少有人讨论了,主要原因就是现在大家都是使用X86平台,这样就像C语言这样的编程语言在相同计算硬件下int类型字节数也是一样的。那么,在python语言中这个问题又是如何的呢?
参考:https://blog.csdn.net/weixin_39997173/article/details/109947726
import sys print(type(0), end=' ')
print(sys.getsizeof(0))# 24 print(type(1), end=' ')
print(sys.getsizeof(1))# 28 print(type(2), end=' ')
print(sys.getsizeof(2))# 28 print(type(2**15), end=' ')
print(sys.getsizeof(2**15))# 28 print(type(2**30), end=' ')
print(sys.getsizeof(2**30))# 32 print(type(2**128), end=' ')
print(sys.getsizeof(2**128))# 44
从上面的代码中,我们可以知道,python语言中int类型的字节数是不固定的,具体使用多少字节数是与这个int类型的表示大小有关的,具体解释见:https://blog.csdn.net/weixin_39997173/article/details/109947726
既然我们知道了python中int类型的特性,那么在python中使用int类型进行位运算时我们不需要考虑int类型的表示范围。在参与运算的数为正数情况下,如果二元运算则需要考虑int类型的数值部分最大的那个数的二进制表示,并对数值部分小的那个数进行补0;如果是一元运算也只考虑数值部分的二进制表示,不需要考虑补0操作。如果参与运算的数为负数,先将其当做正数写出原码形式并补0,然后再对补0后的数的符号位置为负并求补码参与运算。
具体操作:(0b代表符号位为正,-0b代表符号位为负)
1. 与、或操作
与操作:
-22 & -7 = -24
-22的补码为-0b01010,7的补码为0b111,由于7的补码位数小于22,补0后得到7的补码为0b00111,因此参与计算的-7的补码为-0b11001,
因此,参与与操作的两个数分别为-0b01010和-0b11001,因此得到运算结果的补码:-0b01000,(符号位参与运算)
对-0b01000求补码得:-0b11000,即-24。
或操作:
-22 | -7 = -24
-22的补码为-0b01010,7的补码为0b111,由于7的补码位数小于22,补0后得到7的补码为0b00111,因此参与计算的-7的补码为-0b11001,
因此,参与或操作的两个数分别为-0b01010和-0b11001,因此得到运算结果的补码:-0b11011,(符号位参与运算)
对-0b11011求补码得:-0b00101,即-5。
2. 异或操作
22 ^ 7 = 17
22的补码为0b10110,7的补码为0b111,由于7为正数并且补码的位数小于22,于是对7的补码进行补0操作,得到:0b00111
因此,参与异或操作的两个数分别为0b10110和0b00111,因此得到运算结果的补码:0b10001,
对0b10001求补码得:0b10001,即17。
-22 ^ -7 = 19
-22的补码为-0b01010,7的补码为0b111,由于7的补码位数小于22,补0后得到7的补码为0b00111,因此参与计算的-7的补码为-0b11001,
因此,参与异或操作的两个数分别为-0b01010和-0b11001,因此得到运算结果的补码:0b10011,(符号位参与运算)
对0b10011求补码得:0b10011,即19。
3. 非操作
~10 = -11
10的补码为0b 1010,对其取反操作得-0b 0101(此过程中符号位参与运算),得到我们想要的运算结果的补码形式;
我们再对-0b 0101求补码即可得到想要的运算结果的原码形式:-0b 1011,即-11 。
~(-2)= 1
-2的补码为-0b 10,对其取反操作得0b 01(此过程中符号位参与运算),得到我们想要的运算结果的补码形式;
我们再对0b 01求补码即可得到想要的运算结果的原码形式:0b 01,即 1 。
~(-3)= 2
-3的补码为-0b 01,对其取反操作得0b 10(此过程中符号位参与运算),得到我们想要的运算结果的补码形式;
我们再对0b 10求补码即可得到想要的运算结果的原码形式:0b 01,即 2 。
4. 移位操作
-7<<2
7的补码为0b 111,因此,-7的补码为-0b 001,对其左移2位得-0b 00100(此过程中符号位不参与运算),得到我们想要的运算结果的补码形式;
我们再对-0b 00100求补码即可得到想要的运算结果的原码形式:-0b 11100,即 -28 。
也可以这样计算:
因为 7<<2 = 28,因此 -7<<2 = -28 。
===============================
在python中由于int的表示范围是不固定的,因此如果参与位运算的int数为负,那么我需要给与其足够大的表示范围才可以,也就是说要对其正数表示下的数补足够的零;不过更为直接的方法就是按照C语言中的标准,对python中参与位运算的数直接使用一个较大的统一的表示范围,如:2**8以内的数用8个数位来表示,2**16以内的数用16个数位来表示,2**32以内的数用32个数位来表示。
----------------------------------------------
Python示例——负数的位运算的更多相关文章
- Java负数的位运算
/** * 求负数的位运算 *///1. -10 >> 2 = ?//2. -10的原码: 1000 0000 0000 0000 0000 0000 0000 1010 最高位代表符号位 ...
- 4.Python 进制和位运算
.button, #logout { color: #333; background-color: #fff; border-color: #ccc; } span#login_widget > ...
- 简简单单学会C#位运算
一.理解位运算 要学会位运算,首先要清楚什么是位运算?程序中的所有内容在计算机内存中都是以二进制的形式储存的(即:0或1),位运算就是直接对在内存中的二进制数的每位进行运算操作 二.理解数字进制 上面 ...
- C 进制 类型说明符 位运算 char类型
一 进制 1. 什么是进制 是一种计数的方式 数值的表示形式 2. 二进制 1> 特点: 只有0和1 逢2进1 2> 书写格式: 0b或者0B开头 3> %d 以带符号的十进制形式输 ...
- 剑指offer用位运算实现两个数相加,及python相关的位操作
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 代码: # -*- coding:utf-8 -*-class Solution: def Add(self ...
- python位运算
什么是位运算 位运算就是把数字当成二进制来进行计算,位运算有六种:&(与), |(或), ^(异或), ~(非), <<(左移), >>(右移) &(与) &a ...
- Python语言中的按位运算
(转)位操作是程序设计中对位模式或二进制数的一元和二元操作. 在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多. 在现代架构中, 情况并非如此:位运算的运算速度通常与加 ...
- Python 进制转换、位运算
一.进制转换 编程用十进制,十进制转换为二进制.八进制.十六进制 In [135]: bin(23) Out[135]: '0b10111' In [136]: oct(23) Out[136]: ' ...
- Python笔记_第一篇_面向过程_第一部分_3.进制、位运算、编码
通过对内存这一个部分的讲解,对编程会有一个相对深入的认识.数据结构是整个内存的一个重要内容,那么关于数据结构这方面的问题还需要对进制.位运算.编码这三个方面再进行阐述一下.前面说将的数据结构是从逻辑上 ...
- 利用位运算进行a+b的计算(Java&&Python)
题目链接 需要用到的位运算操作:异或(^).与(&).右移(<<) 异或运算:又称不进位加法,a^b得到的结果为a与b相加,但是需要进位的地方不进位得到的结果 与运算:找出来a和b ...
随机推荐
- Vue3:介绍
Vue 3 相较于 Vue 2 在多个方面进行了改进和优化,主要优势包括但不限于以下几个方面: 响应式系统优化: Vue 3 引入了基于 Proxy 的响应式系统,取代了 Vue 2 中基于 Obje ...
- Vue学习:4.v-model使用
第一节算是对v-model的粗略了解,仅仅是将input的输入与Vue 实例的数据之间双向绑定.这一节将更详细的了解v-model在不同表单元素中的使用. v-model实例:找对象 实现功能: 使用 ...
- nordic—RTC+PPI定时驱动某外设做非单次触发(本次测试为驱动GPIO口做电平翻转)
简介:在nordic的开发中使用到RTC时,对于比较通道0/1/2/3的中断来说,如果不进行相关配置(如SDK中例子,使用的RTC比较通道就只能触发一次,不能多次触发),会导致比较中断只进入一次,如果 ...
- 订单推送设计思路-基于支付ID而不是订单号来推送
订单推送设计思路-基于支付ID而不是订单号来推送 方案:不是基于订单号来核销和分账的,抖音是基于每一笔抖音支付来做订单推送,核销和分账现象:这样会在抖音的订单中心中会出现很多条订单推送的记录. 抖音A ...
- python 注册nacos 进行接口规范定义
背景: 一般场景 python服务经常作为java下游的 算法服务或者 数据处理服务 但是使用http 去调用比较不灵活,通过注册到nacos上进行微服务调用才是比较爽的 1.定义feginapi的接 ...
- Xcode编译错误看不到错误详情
问题描述 Xcode提示错误后想详细看报错信息无论如何双击都不见弹出错误详情. 解决办法 不知道是bug还是苹果婊又自作主张改变用户习惯了,需要点击navigator最右边的一个图标,在里面找到相应的 ...
- 01-前端开发Vscode插件配置
01 自动保存配置 02 空格渲染方式 配置好以后,可以看到代码的空格有几个,以点的方式呈现,1个点表示1个空格 03 图标插件 VSCode Great Icons 04 缩进 推荐使用2 05 v ...
- 图片接口JWT鉴权实现
图片接口JWT鉴权实现 前言 之前做了个返回图片链接的接口,然后没做授权,然后今天键盘到了,也是用JWT来做接口的权限控制. 然后JTW网上已经有很多文章来说怎么用了,这里就不做多的解释了,如果不懂的 ...
- HTTP 协议学习:1-HTTP概述
背景 原文:HTTP概述 HTTP是一种能够获取如 HTML 这样的网络资源的 protocol(通讯协议).它是在 Web 上进行数据交换的基础,是一种 client-server 协议,也就是说, ...
- ARC108C
考虑一颗树怎么染色. 每个子节点染成边的颜色,如果与父亲节点相同,就随便染色(这条边的限制已经被父亲节点满足). 那么一定可以染色. 所以把原图跑最小生成树再按上述方法染色即可. 倘若原图不连通,那么 ...