计算机中无符号整数和有符号整数

文章介绍了计算机中数的两种表示方式——有符号整数和无符号整数,强调了最高位作为符号位的区别以及无符号数不能表示负数的特点。此外,还讨论了补码的概念及其在存储负数和简化计算中的作用。同时,提到了不同类型之间的转换规则,特别是有符号数和无符号数之间的转换策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概念

计算机里的数是用二进制表示的,最左边的这一位一般用来表示这个数是正数还是负数,这样的话这个数就是有符号整数(signed integer)。如果最左边这一位不用来表示正负,而是和后面的连在一起表示整数,那么就不能区分这个数是正还是负,就只能是正数,这就是无符号整数(unsigned integer)。

计算机中的整数分为两类:不带符号位的整数(unsigned integer,也称为无符号整数),此类整数一定是正整数;带符号位的整数(signed integer),此类整数可以表示正整数,又可以表示负整数。

简明的说,无符号数就是其所有的位数都用来表示数值的大小,有符号数除最高位来表示数值的正负外(0表示正数;1表示负数),其余各位用来表示数值的大小。

举个例子说明一下:

十机制数 正数255  二进制表达形式:1111 1111
十机制数 负数-1     二进制表达形式:1111 1111 

可见-1的二进制的最高位为红色的1,可是为什么其表达形式为1111 1111而不是1000 0001呢?这就关于任何数在计算机内是以补码形式存储问题,下面会介绍的。

2.存储范围

从前面的介绍可以知道,由于有符号数的最高位被拿来用作符号位,所以它所能够表达的最大数值要小于无符号数所能够表达的最大数值。还是举个例子来说明一下吧:

无符号数:1111 1111 十进制值:255

有符号数:0111 1111 十进制值:127

这是有人可能会提出这样的疑问:有符号数所能够表达的数值范围会不会小于无符号数所能够表达的数值范围呢?

答案是否定的!虽然有符号数在表达最大值上的能力减弱了,但是它能够表达负数。负数的个数可以弥补其不足。来让我们比较一下:

一个字节的无符号数的表达数值范围是:[0,255]
一个字节的有符号数的表达数值范围是:[-128,0),[0,127]

可见它们都能够表示256个数。
 

无符号整数常用于表示地址、索引等正整数,它们可以是8位、16位、32位、64位甚至更多。

8个二进制表示的正整数其取值范围是         0~255(2f1b4aa003571aee9013308d1edd2627.png -1)

16位二进制位表示的正整数其取值范围是    0~65535( a1c948759f8e500b5178b97787f87023.png -1)

32位二进制位表示的正整数其取值范围是    0~ 06344efd866c091b03aa869300577859.png-1

有符号和无符号的差别:

int是有符号的,unsigned是无符号的。

它们所占的字节数其实是一样的,但是有符号的需要安排一个位置来表达我这个数值的符号,因此说它能表示的绝对值就要比无符号的少一半。举个例子,我们有一个1个 [1]  字节的整数(虽然这种类型不存在),那么无符号的就是这样:00000000~11111111 这个就是无符号的范围。

一个字节是8位, 有符号的数,因为第一个位要用来表示符号,那么就只剩下7个位置可以用来表示数了0000000~1111111因为有符号,所以还可以表示范围:-1111 111 ~ +1111 111。

3.各种码(原码/反码/补码)

有些人也许会这样认为"-1"(双字节)在计算机中的表达形式为1000 0000 0000 0001,可是实际上不是的。计算机是以其补码的形式进行表达的,即“-1”(双字节)的表达形式是1111 1111 1111 1111。

说一下各种码的概念吧。

原码:一个整数,按照绝对值的大小转换成二进制数,最高位为符号位。

反码:将原码除最高位(符号位)外,其余各位按位取反,所得到的二进制码。正数的反码为原码。

补码:反码最低位加1即为补码。

关于负数的补码求法说明一下,先得到其反码,之后将反码加1即可。有些大神根据其原码,闭眼即得,这种能力需要修炼一下啊。

这时有些人可能会说,为什么要引入补码的形式呢?直接按照原码存储不就省事很多吗?嘿嘿,要记住,有些事情并不是你想省事就能省事的。好了来欣赏一下补码的优势吧。

计算机的带符号数用补码表示的优点:

1负数的补码与对应正数的补码之间的转换可以用同一种方法-求补运算完成,可以简化硬件。 2 可将减法变为加法,这样减法就可以用加法器进行计算了。 3 两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。


心算求补(大神求补算法):

从最低位开始至找到的第一个1均不变,符号位不变,这之间的各位“求反”(0变1;1变0)。
原码:1010 1001  补码:1101 0111.

4.有符号数与无符号数的相互转换

无符号整数和有符号整数之间进行强制类型转换时,位模式不改变。

有符号数转换为无符号数时,负数转换为大的正数,相当于在原值上加上2的n次方,而正数保持不变。

无符号数转换为有符号数时,对于小的数将保持原值,对于大的数将转换为负数,相当于原值减去2的n次方。

当表达式中存在有符号数和无符号数类型时,所有的操作都自动转换为无符号类型。可见无符号数的运算优先级高于有符号数。

5.转换大餐

有符号数的转换 

原类型目标类型转换方法
char

short

符号位扩展
charlong符号位扩展
charunsigned char最高符号位失去位意义,变为数据位
charunsigned short符号位扩展到short;然后从short转到unsigned short
charunsigned long符号位扩展到long;然后从long转换到unsigned long
charfloat符号位扩展到long;然后从long转到float
chardouble符号位扩展到long;然后从long转换到double
charlong double符号位扩展到long;然后从long转换到long double
shortchar保留低位字节
shortlong符号位扩展
shortunsigned char保留低位字节
shortunsigned short

最高为失去意义,变为数据位

shortunsigned long符号位扩展到long;然后从long转到unsigned long
shortfloat符号位扩展到long;然后从long转到float
shortdouble符号位扩展到long;然后从long转到double
shortlong double符号位扩展到long;然后从long转换到long double
longchar保留低位字节
longshort保留低位字节
longunsigned char保留低位字节
longunsigned short保留低位字节
longunsigned long最高为失去意义,变为数据位
longfloat使用单精度浮点数表示,可能失去精度
longdouble使用单精度浮点数表示,可能失去精度
longlong double使用单精度浮点数表示,可能失去精度

无符号数的转换

原类型目标类型转换方法
unsigned charchar最高为作符号位
unsigned charshort0扩展
unsigned charlong0扩展
unsigned charunsigned short0扩展
unsigned charunsigned long0扩展
unsigned charfloat转换到long;然后从long转换到float
unsigned chardouble转换到long;然后从long转换到double
unsigned charlong double转换到long;然后从long转换到long double
unsigned shortchar保留低位字节
unsigned shortshort最高为作符号位
unsigned shortlong0扩展
unsigned shortunsigned char保留低位字节
unsigned shortunsigned long0扩展
unsigned shortfloat转换到long;然后从long转换到float
unsigned shortdouble转换到long;然后从long转换到double
unsigned longlong double转换到long;然后从long转换到long double
unsigned longchar保留低位字节
unsigned longshort保留低位字节
unsigned longlong最高位作符号位
unsigned longunsigned char保留低位字节
unsigned longunsigned short保留低位字节
unsigned longfloat转换到long;然后从long转换到float
unsigned longdouble直接转换到double
unsigned longlong double转换到long;然后从long转换到long double

<think>嗯,用户的问题是关于无符号整数有符号整数相减的运算规则及实现。首先,我需要回忆一下计算机组成原理中的相关知识,特别是补码表示运算规则。 根据引用[1],无符号小数减大数的时候,会转换成补码运算,结果作为无符号数的真值。例如,1-2的结果是补码相加后的11111111,即255的无符号值。而有符号数的运算则涉及原码、反码、补码的转换。 接下来,用户想知道无符号有符号混合运算时的规则。这时候应该考虑类型转换的问题。通常,在C语言等环境中,运算时会将有符号数转换为无符号数,然后进行运算。例如,intunsigned int相减,int会被转为unsigned int,可能导致负数变成很大的正数。 比如,-2(有符号3(无符号)相减。在32位系统中,-2的补码是0xFFFFFFFE,转换成无符号数就是4294967294。然后3 - 4294967294会溢出,结果可能变成(3 - 4294967294) mod 2^32,即4294967305,但可能需要更仔细的计算。 然后要考虑运算时的位模式处理。无论是否有符号,硬件层面都是按补码运算,但结果的解释方式不同。例如,两个数相减后的二进制结果,如果是无符号运算,就直接解释为无符号数;如果是有符号,则看最高位是否为1来判断正负。 用户可能还需要了解溢出处理。无符号数溢出会取模,而有符号数溢出是未定义行为。不过,硬件运算时,标志位会被设置,比如进位溢出标志,但编程语言层面的处理可能不同。 最后,用户可能关心实际编程中的例子,比如C语言中的情况,以及如何避免错误。比如,当有符号数为负数时,转换成无符号数可能导致意想不到的大数,从而影响计算结果。 需要确保回答结构清晰,分步骤解释规则、实现机制、示例分析以及注意事项,并生成相关问题帮助用户深入理解。</think>### 无符号整数有符号整数相减的运算规则及实现 #### 一、运算规则的核心逻辑 1. **类型转换优先级** 当无符号整数有符号整数进行运算时,**有符号整数会被隐式转换为无符号整数**,运算按无符号整数规则执行[^1]。例如: - 若 `unsigned int a = 3`,`int b = -2`,则 `a - b` 等价于 `a + (unsigned int)(-b)`,但需注意负数的补码表示对结果的影响。 2. **补码运算的统一性** 计算机硬件层面**统一使用补码进行加减运算**,无论操作数是有符号还是无符号。结果的解释方式取决于变量类型: - 若结果赋给有符号变量,按补码解释为有符号数; - 若赋给无符号变量,按二进制原值解释为无符号数[^1][^2]。 #### 二、具体实现机制 1. **位模式操作示例** 以8位数为例: - 无符号数 `1`(`0000 0001`)与有符号数 `-2`(补码 `1111 1110`)相减: $$0000\ 0001 + 1111\ 1110 = 1111\ 1111$$ 若结果按无符号解释为255,按有符号解释为-1。 2. **溢出处理差异** - **无符号数溢出**:结果取模(如8位数范围0~255),例如 `0 - 1 = 255`; - **有符号数溢出**:属于未定义行为(UB),但硬件可能通过溢出标志位检测。 #### 三、编程语言中的实际行为(以C语言为例) ```c unsigned int u = 5; int s = -3; unsigned int result = u - s; // s被转换为无符号数,-3的补码为超大正数 ``` 此时 `s` 的二进制补码被直接解释为无符号数(32位下为 `4294967293`),最终 `result = 5 + 4294967293 = 4294967298`,超出32位范围后实际结果为 `2`(模 $2^{32}$)。 #### 四、注意事项 1. **隐式转换风险** 混合类型运算可能导致预期外的巨大正值(如负数转为无符号数)。 2. **显式类型控制** 建议通过强制类型转换明确运算意图,例如: ```c int a = 10; unsigned int b = 20; int result = (int)(b - (unsigned int)a); // 显式统一类型 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值