标签:一个 order 相加 浮点数 解决 app lin 编程语言 超出
我们怎么看懂二进制的大小呢?换句话说,二进制怎么转化成十进制来理解呢?举个例子,比如说有一个8位的二进制数“01011011”如下,转换为十进制的,应该怎么转化?二进制数的每一位数都是2的几次幂,就像我们的十进制一样,0是10的0次幂(100),10是10的1次幂(101),100是10的2次幂(102)。上述“01011011”对应每个位置的幂数如下:二进制数转化十进制就是每个位所代表的数值和每个位的数值相乘后相加,也就是:(27 * 0) + (26 * 1) + (25 * 0) + (24 * 1) + (23 * 1) + (22 * 0) + (21 * 1) + (20 * 1)因为整数乘0等于0,乘1等于本身,那么上述计算可简化为:26 + 24 + 23 + 21 + 20 = 64 + 16 + 8 + 2 + 1 = 91也就是说,我们只需要计算数字为1的位所代表十进制数的和就可以了。那我们知道了二进制转十进制,那十进制如何转二进制呢?我们可以使用求余的方法计算,比如刚才的91,如下图:由下往上将余数组合起来就是“1011011”,前面补0凑齐8位就是01011011。2、二进制的运算规则。十进制的计算规则我们都很清楚了,那么二进制又是怎么计算的呢?其实是有规律的,因为只有0、1两个数,规则就简单很多:加法:0 + 0 = 0, 0 + 1 = 1, 1 + 0 = 1, 1 + 1 = 10(进1位)减法:0 - 0 = 0, 1 - 0 = 1, 1 - 1 = 0, 0 - 1 = 1(借1位)乘法:0 × 0 = 0, 1 × 0 = 0, 0 × 1 = 0, 1 × 1 = 1除法:0 ÷ 1 = 0, 1 ÷ 1 = 1(0不能为除数)看起来很多,其实细看一下,跟十进制是一样的,只不过是“逢2进1”的区别,我们可以举例看一下,比如使用1001和0101的四则运算如下图所示:二进制的运算,一般比较少用到,更为常用的是与、或、非、异或的运算,规则更为简单:与:1 & 1 = 1, 1 & 0 = 0, 0 & 1 = 0, 0 & 0 =0(其实就是0和任意数字做与运算都为0,与的符号为&)或:1 | 1 = 1, 1 | 0 = 1, 0 | 1 = 1, 0 | 0 = 0(1和任意数字做或运算都为1,或的符号为|)非:~1 = 0, ~0 = 1(其实就是取反,反过来了,非的符号为~)异或:1 ^ 1 = 0,1 ^ 0 = 1, 0 ^ 1 = 1, 0 ^ 0 = 0(相同的为0, 不同的为1,异或的运算符为^)3、我们学了2.1节之后就知道数值有整数和浮点数之分,整数的存储我们比较好理解,就是通过二进制的存储方式来存储十进制。但是如果有负数我们应该怎么存储呢?所以整数可以分为有符号数和无符号数。有符号数:计算机将存储的最高位用来作为符号位,最高位为0,表示正数,最高位为1,表示负数。无符号数:将全部位数用来表示数值,没有符号位,不能表示负数。我们知道了计算机存储整数的方法,那么计算机做整数运算的话该怎么计算呢?举个例子,如果计算1 - 1的话,按照我们已知的计算方法应该是如下计算:1 - 1 = 1 + (-1) = (00000001) + (10000001) = 10000010 = -2 ≠ 0这显然是不正确的。为了解决这个问题,整数又分了三种编码方式:原码、反码、补码。原码:在数值前面增加了一位符号位(即最高位为符号位),该位为0表示正数,该位为1表示负数,其余位表示数值的大小。反码:正数的反码与其原码相同。负数的反码是对其原码逐位取反,但符号位除外。补码:正数的补码与其原码相同,负数的补码就是对该负数的反码加1。0的补码为0。【从定义可以看出,正数的补码,反码,原码相同。0的补码就是本身。那么负数的原码和补码如何转换呢?已知一个负数求补码方法:绝对值原码按位求反加1。已知负数补码求负数方法:符号位不变,其他位按位求反加1。】反码能解决上述问题吗?我们再算一下:1的反码为000000001,-1的反码为11111110,计算如下:1 - 1 = 1 + (-1) = (00000001) + (11111110) = 11111111 = -01 - 2 = 1 + (-2) = (00000001) + (11111101) = 11111110 = -1结果都是正确的,但是又有一个问题,0是没有+0和-0的区别的。我们在看一下补码的计算:1 - 1 = 1 + (-1) = 00000001 + 11111111 = 00000000 = 01 - 2 = 1 + (-2) = 00000001 + 11111110 = 11111111 = -1结果都是正确的,显然,计算机使用补码来存储和计算是比较方便的。在Python里面,整数是无限大的,理论上内存多大,整数就可以多大,所以int类型的数据没有范围,但是如果在C语言中,int类型则有一些受限,比如是在32位的电脑中,int占32位,取值范围为-2147483648~2147483647(-2^32~2^32-1)。如果超出范围怎么办,那就有“溢出”的风险,比如说4位范围的数,最大已经到了1111,如果这个时候再加1,则会变成10000了,而程序只能读4位,该数值就变成0,我们称为溢出。C语言更为关心计算机底层,所以编写C语言则需要格外小心。C语言还有long类型和long long类型,来表示更大的数值范围。在python2还有long类型,在Python3里面就没有了。我们可以更关心我们的编程逻辑而不用担心更加底层的问题4、知道了整数的存储和计算之后我们再聊一下小数,其实不是所有小数都叫做浮点数,浮点数是一种表示数字的标准,整数也可以用浮点数的格式来存储。小数的表示方法除了浮点数还有定点数,区别就是小数点能不能“浮动”,浮点数的小数点在逻辑上是不固定的。浮点数可以用一个表达式来表示:V = (-1)s × M × 2E我们来逐个解释一下:符号(sign) :1个bit表示,当s=0,V为正数;当s=1,V为负数。阶码(exponent) :E的作用是对浮点数加权,用于存储科学计数法中的指数数据,并且采用移位存储。尾数(significand) :M是一个二进制小数,因为是二进制,所以科学计数法中这个值范围是:1≤M<2。(和十进制中范围为1~10一样)一般在编程语言(如C语言)中浮点类型一般是采用单精度(float)和双精度(double)来存储,float数据占用32bit,double数据占64bit。在python中是使用了双精度来存储float,没有double。
说完尾数M,我们再说一下指数E。我们上面只讲到正整数的指数,但科学计数法中,指数是有负数的,而E是一个无符号数,因为它没有符号位,于是IEEE又规定了,在保存真实E值时,E要加一个中间值。单精度情况下,E加127,双精度情况下,E加1023,这样负数也能存进来了。另外,当E取值不同时,对整数值的计算方法也不一样,有下面三种情况。① 当E不全为0,也不全为1时:表示规格化形式的数字,按正常计算。此时E减去中间值得到真实值,M的整数部分按上面说的取值为1。② 当E全为0时:表示非规格化形式的数字,主要是0或者非常接近于0的数。此时E减去中间值得到真实值,M的整数部分取0。③ 当E全为1时:表示特殊值。如果M全为0,表示±无穷大(正负取决于符号s),如果M不全为0,表示这不是一个数(NaN)。
标签:一个 order 相加 浮点数 解决 app lin 编程语言 超出
原文地址:https://www.cnblogs.com/sunshinesky/p/12343852.html