1、无符号数、有符号数、补码
C 语言是支持多种整型数据类型的,下面我们看一下在 32 位机器和 64 位机器中,C 语言整型数据类型的取值范围。
无符号数,在C语言中,即用 unsigned 声明的整数。
定义:假设对于一个w位的无符号整数,用二进制比特位可以表示为[xw-1 , xw-2 , … , x2 , x1 , x0]。
最常见的有符号数表示方式就是补码形式,通过将字的最高有效位解释为负权。
通过几个测试例子来解释有符号数、无符号数和补码:
1)、+9的补码是00001001。+9 为无符号数,补码为原码。
2)、-5对应正数5(00000101)→所有位取反(11111010)→加1(11111011),-5的补码需要按位取反,然后末位加一
3)、[+0]补=[+0]反=[+0]原=00000000 ,[ -0]补=11111111+1=00000000 。 数字 0 的补码是唯一的。
2、浮点数
理解浮点数的第一步是考虑含有小数值的二进制数字
例如:10.111(2) = 2+0+1/2+1/4+1/8=2 +7/8
但是小数的二进制表示法只能表示为 x 乘以 2 的 y 次方,如果不能写成这种方式的只能近似的表示,由此可见,二进制表示十进制数是不精确的。数字 1/5 可以用十进制表示为 0.20 ,不过我们并不能把它准确的表示为一个二进制小数,只能近似的表示,增加二进制的长度可以提高精度,但是范围和精度又是一对矛盾体。
IEEE 浮点标准表示: V = (-1)s * M * 2E。
①、s 是符号位,为0时表示正,为1时表示负。
②、M为尾数,是一个二进制小数,它的范围是0至1-ε,或者1至2-ε(ε的值一般是2-k次方,其中设k > 0)
③、E为阶码,可正可负,作用是给尾数加权。
我们将浮点数的位划分为三个阶段,分别对这些值进行编码。
一、一个单独的符号位 s 直接编码符号 s
二、k 位的阶码字段 exp =ek-1ek-2...e1e0 编码阶码E
三、n 位小数字段 frac = fn-1fn-2...f1f0 编码尾数 M,但是编码出来的值也依赖于阶码字段的值是否等于0.
一般来说,现在的编译器都支持两种浮点格式,一种是单精度,一种是双精度。单双精度分别对应于编程语言当中的float和double类型。其中float是单精度的,采用32位二进制表示,其中1位符号位,8位阶码以及23位尾数。double是双精度的,采用64位二进制表示,其中1位符号位,11位阶码以及52位尾数。如下图表示:
如果给定了位 s 的表示,根据 exp 的值,被编码的值可以分为三种不同的情况(最后一种情况有两个变种)。下图是单精度的情况:
规格化的值:这是最普遍的情况,当 exp 位既不全为 0 ,也不全为 1 时,都属于这种情况。在这种情况下,阶码字段被解释为偏置。也就是说,阶码值为 E = e - bias 。e 表示无符号数,bias 表示偏移值(单精度127,双精度 1023)
小数字段 frac 被解释为描述小数值 f,尾数定义为 M=1+f ,这种表示法是一种轻松获得额外精度的技巧,既然第一位总是等于 1 ,那我们就不要显式的表示它。
举例:浮点数 5.8(单精度表示)
5.8=1.45x2x2
位 s : 0
阶码:2 ,然后 8 位阶码既要表示负数又要表示正数,127+2 =129 =10000001
尾数:不断地乘2,取结果的整数部分就行
所以 5.6 的二进制表示为:01000000101110011001100110011001
非规格化的值:当阶码域全为0时,所表示的数是非规格化形式。
功能一:提供一种表示 0 的方法,因为规格化值M>=1 ,因此就不能表示 0。实际上当符号位为 0 时,表示的是+0.0,当符号位为 1 时,表示的 -0.0。
功能二:表示那种非常接近 0 的数,称为逐渐溢出,其中,可能的数值均匀地接近0.0
特殊值:当阶码全为 1 的时候,当小数域全为 0 ,得到的数无穷,当 s=1,表示负无穷,s=0,表示正无穷。当两个非常大的数相乘,或者除以零时,无穷能够表现出溢出的结果。 当小数域不为0时,就会返回NaN,不是一个数 Not a Number。一些运算的结果不能是实数或无穷,就会返回这样的结果。
网友评论