标签:
正数的原码、反码以及补码是其本身。
负数的原码是其本身,反码是对原码除符号位之外的各位取反,补码则是反码加1。
能够统一+0和-0的表示
采用原码表示,+0的二进制表示形式为0 000 0000,而-0的二进制表示形式为1 000 0000;
采用反码表示,+0的二进制表示形式为0 000 0000,而-0的二进制表示形式为1 111 1111;
采用补码表示,+0的二进制表示形式为0 000 0000,而-0的二进制表示形式为1 111 1111+1=1 0000 0000,因为计算机会进行截断,只取低8位,所以-0的补码表示形式为0000 0000。
补码的表示范围比原码和反码表示的范围都要大。用补码能够表示的范围为-128~127,0~127分别用00000000~01111111来表示,而-127~-1则用10000001~11111111来表示,多出的10000000则用来表示-128。
对于有符号整数的运算能够把符号位同数值位为一起处理
如果把符号位单独考虑的话,CPU指令还要特意对最高位进行判断,使计算机的最底层实现变得复杂。
参考资料:整数溢出与程序安全
一个整数是一个固定的长度,它能存储的最大值是固定的,当尝试去存储一个大于这个固定的最大值时,将会导致一个整数溢出。
整数溢出将会导致"不能确定的行为"。大多数编译器会忽略整数溢出,致使整数溢出没有立即察觉,因此没有办法去用一个应用程序来判断先前计算的结果在实际上是否也是正确的,可导致某些类型的bugs,缓冲区溢出等。
每个计算机都有一个字长,指明整数和指针数据的标称大小。因为虚拟地址是以这样的一个字来编码的,所以字长最重要的系统参数就是虚拟地址空间的最大大小。
对于一个字长为w位的机器而言,虚拟地址的范围为0~2^w-1,程序最多访问2^w字节。
字节顺序是网络编程的基础,是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序。
小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处。
大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处。
逻辑运算
所有逻辑运算都可以用与、或、非表达(最大式、最小式)而与或非可以用“与非”或“或非”表达,所以,只要一个与非门,就可以完成所有的逻辑运算。
逻辑与(&&) 遇0为0;
逻辑或(||) 遇1为1;
逻辑非 遇0为1,遇1为0;
位运算
结果是位向量
按位与(&) 二进制每一位遇0为0;
按位或(|) 二进制每一位遇1为1;
按位异或(^) 0^0=0,0^1=1,1^0=1,1^1=0;
按位取反(~) 二进制每一位取反。
掩码运算
掩码是位运算的重要应用,这里掩码是一个特定位模式,表示从一个字中选择一个位的集合。对特定位可以置一,可以清零。
逻辑运算与掩码运算
如果对第一个参数求值就能确定表达式的结果,逻辑运算符就不会对第二个参数求值。
char 字符型数据,占用一个字节
unsigned char 无符号字符型数据,占用一个字节
short 短整形数据,占用两个字节
unsigned short 无符号短整型数据,占用两个字节
int 整形数据,占用两个字节
unsigned int 无符号整型数据,占用两个字节
long 长整型数据,占用四个字节
unsigned long 无符号长整型数据,占用四个字节
对于长度为w的位向量,都有一个唯一的值与之对应;反过来,在0~2^w-1之间的每一个整数都有一个唯一的长度为w的位向量二进制表示与之对应。
有符号整数最常见的表示方法:二进制补码形式。
二进制补码形式的三个特点:
1)二进制补码的范围是不对称的:|TMin|=|TMax|+1,即不存在与最小值相对应的整数,这容易造成程序中细微的错误。
2)位数相同的前提下,无符号数的最大值刚好是二进制补码最大值的2倍加1:UMax=2TMax+1。
3)二进制补码中的-1与UMax有相同的位表示——全1位串。
ANSI C标准并未规定使用二进制补码形式来表示有符号整数,但是几乎所有的机器都是这么做的。补码利用寄存器长度固定的特性简化数学运算,将数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。
二进制反码形式:与二进制补码的表示方法类似,区别在于最高有效位的权值不同。
原码:最高有效位是符号位,确定剩下的位取负权值还是正权值。
这两种表示都有一个奇怪的属性,即对于数字0存在两种编码。对于两种方法,[00..0]都被解释成+0 ,而-0在二进制反码中表示为[11..1] ,在原码中表示为[10..0]。
虽然曾经有过基于二进制反码表示法的机器,但几乎所有现代机器都使用二进制补码。
符号数值编码方式使用在浮点数的表示中。
ANSI C规定在无符号整数和有符号整数之间进行强制类型转换时,并未改变对象的位模式,改变的是位模式的解释方式。处理同样字长的有符号数和无符号数之间相互转换的一般规则是:数值可能会改变,位模式不变。
T2U:补码到无符号数的转换
U2T:无符号数到补码的转换
有符号数转换为无符号数时,负数转换为大的正数(可以理解为原值加上2的n次方),而正数保持不变。
x<0 T2Uw(x)=x+2^w
x>0 T2Uw(x)=x+2^w
(*w表示数据类型的位数)
无符号数转换为有符号数时,对于小的数将保持原值,对于大的数则转换为负数(可以理解为原值减去2的n次方)
u<2^(w-1) U2Tw(u)=u
u>=2^(w-1) U2Tw(u)=u-2^w
(*w表示数据类型的位数)
C语言允许无符号数和有符号数之间的转换,转换的原则是底层的位保持不变。
显式转换:强制类型转换。
隐式转换:一种类型的表达式被赋值给另外一种类型的变量时。
C语言在处理同时包含无符号数和有符号数的表达式时,会隐式的将有符号数转换为无符号数,并假设这两个操作数都是非负的,然后执行运算。这一特性对于标准的算术运算来说无多大差异,但对于像"<"和">"这样的关系运算符,有时会导致和直觉不相符的结果。
例:当一个有符号数“-1”与无符号数“0”用关系运算符连接时,会自动的将-1隐式转换为无符号数4294967295(假设是一个使用补码的32位机器),负数变成了正数,“-1<0u”的结果值就是0。
-C语言的强制类型转换
零扩展:要将一个无符号数转换为一个更大的数据类型,只需简单的最高位前加0。
符号扩展:将一个补码数字转换为一个更大的数据类型,在表示中添加最高有效位值的副本。
截断一个数字可能会改变其值,这也是值溢出的一种形式。,
无符号数x,将其截断成k位,mod 2^k。
有符号数x,先将其看作无符号数截断,然后在转换成有符号数。
"字长膨胀"
无符号运算可以被视为某种形式的模运算。无符号加法等价与计算取模后的和,可以通过简单的丢弃超出字长的部分来完成取模计算。
算术运算溢出
二进制补码加法在溢出时同样会将结果中超过字长的部分丢弃,然而,这样的结果在数学上却能用取模来等同。
以z=x+y为例,其中x,y,z均为位长为n的有符号数
正溢出:x+y >= 2^(w-1)
z=x+y-2^w x,y为正值,而最终结果z为负值。
负溢出:x+y < -2^(w-1)
z=x+y-2^w x,y为负值,而最终结果z为正值。
补码非运算
对于范围在[-2^(w-1),2^(w-1))中的x,补码的非运算有如下两种情况:
x=-2^(w-1)时,为-2^(w-1)
x>-2^(w-1)时,为-x
位级补码非
设k为最右面的1的位置,将k左边的所有位取反。
对于无符号和补码乘法来说,乘法运算的位级表示都是一样的。
对无符号变量x
x<<k 等价于x*2^k。 (特别地,我们可以用1U<<k来计算2^k)
对二进制补码数x
x<<k 等价于x*2^k。
即使在运算结果溢出时,上述等价关系依然成立。
机器运算中,除法比乘法更慢。当被除数为2的整数次幂时,通过右移来解决。右移时需要区分无符号数和补码。
注意:整数除法总是舍入到零
无符号数——逻辑右移:无符号数除以2的k次幂,就等同于对其逻辑右移k位。
补码——算术右移:补码进行算术左移时,需要考虑补码数的正负,因为整数除法总是舍入到零,无符号数中没有负数不必担心,但补码中有正有负,正数向下舍入到零,负数应该向上舍入到零。所以这里涉及到在移位前偏置。
即:x≥0时,除以2的k次幂等价于将x算术右移k位
x<0时,先将x加上(2^k)-1,再算术右移k位
与乘法不同,这种右移方法不能推广到任意常数C。
IEEE浮点标准
表示一个数: V=(-1)^s * M * 2^E
阶码:E对浮点数加权,权重是2的E次幂(可能为负数)。
n位小数字段 frac = f(n-1)……f1f0编码尾数 M,但是编码出来的值也依赖于阶码字段的值是否等于0.
浮点数可分为三种表达方式
特殊值
exp的位模式既不全0也不全1的时候,这是最一般最普遍的情况,因而是规格化的。
阶码字段被解释为以偏置形式表示的有符号整数。
阶码: E = e-Bias
Bias:偏置值,Bias=[2^(k-1)-1]
尾数 M = 1+f(有时也可称作隐含的以1开头的表示)
阶码域全为0时的数。
特殊值是在阶码位全为1的时候出现的。
IEEE浮点格式定义了四种不同的舍入方法:
向偶舍入(默认) 将数字向上或向下舍入,是的结果的最低有效数字为偶数。能用于二进制小数。
向零舍入 把整数向下舍入,负数向上舍入。
向下舍入 正数和负数都向下舍入。
向上舍入 正数和负数都向上舍入。
默认的(即向偶舍入)方法可以得到最接近的匹配,其余三种产生实际值的确界。
浮点加法
- 可交换
- 不具结合性:缺少的重要群属性
- 大多数值的浮点加法都有逆元,除了无穷和NaN。
- 满足单调性
浮点乘法
- 可交换的
- 不具有结合性:可能发生溢出,或由于舍入而失去精度。
- 乘法单位元为1.0
- 在加法上不具备分配性
- 在一定条件下满足单调性(无符号或补码的乘法没有这些单调性属性)
C标准并未明确要求机器在浮点数的表示上采取IEEE标准 。
int、float、double之间的强制类型转换
- int → float 数字不会溢出,但有可能舍入
- int/float → double 保留精确的数值
- double → float 由于精确度变小,可能溢出为±∞,也有可能被舍入
- float/double → int 可能向零舍入,可能溢出。
1,创建XXX.pl并编辑
2,perl XXX.pl
3,运行./XXX.pl
数值可能改变,但是位模式不变。
标签:
原文地址:http://www.cnblogs.com/20135207oneking/p/4861442.html