-
十进制数转二进制采用的是除 2 取余法
-
int
类型的数字作为例子,int 类型是32
位的,其中最高位是作为「符号标志位」,-
正数的符号位是
0
,负数的符号位是1
,剩余的 31 位则表示二进制数据。 -
负数就比较特殊了点,负数在计算机中是以「补码」表示的,所谓的补码就是把正数的二进制全部取反再加 1
-
如果负数不是使用补码的方式表示,则在做基本对加减法运算的时候,还需要多一步操作来判断是否为负数,如果为负数,还得把加法反转成减法,或者把减法反转成加法.而用了补码的表示方式,对于负数的加减法操作,实际上是和正数加减法操作一样的。
-
-
十进制小数与二进制的转换
-
采用的是乘 2 取整法,将十进制中的小数部分乘以 2 作为二进制的一位,然后继续取小数部分乘以 2 作为下一位,直到不存在小数为止。
-
0.1 的表示
-
由于计算机的资源是有限的,所以是没办法用二进制精确的表示 0.1,只能用「近似值」来表示,就是在有限的精度情况下,最大化接近 0.1 的二进制数,于是就会造成精度缺失的情况。
-
-
-
对于二进制小数转十进制时,需要注意一点,小数点后面的指数幂是负数
-
-
计算机是怎么存小数的?
-
1000.101
这种二进制小数是「定点数」形式,代表着小数点是定死的,不能移动,如果你移动了它的小数点,这个数就变了, 就不再是它原来的值了。 -
计算机并不是这样存储的小数的,计算机存储小数的采用的是浮点数,名字里的「浮点」表示小数点是可以浮动的。
-
比如
1000.101
这个二进制数,可以表示成1.000101 x 2^3
,类似于数学上的科学记数法。 -
该方法在小数点左边只有一个数字,而且把这种整数部分没有前导 0 的数字称为规格化
-
比如
1.0 x 10^(-9)
是规格化的科学记数法,而0.1 x 10^(-9)
和10.0 x 10^(-9)
就不是了
-
-
如果二进制要用到科学记数法,同时要规范化,那么不仅要保证基数为 2,还要保证小数点左侧只有 1 位,而且必须为 1。
-
通常将
1000.101
这种二进制数,规格化表示成1.000101 x 2^3
,其中,最为关键的是 000101 和 3 这两个东西,它就可以包含了这个二进制小数的所有信息:-
000101
称为尾数,即小数点后面的数字; -
3
称为指数,指定了小数点在数据中的位置;
-
-
double 的尾数部分是 52 位,float 的尾数部分是 23 位,由于同时都带有一个固定隐含位(这个后面会说),所以 double 有 53 个二进制有效位,float 有 24 个二进制有效位,所以所以它们的精度在十进制中分别是
log10(2^53)
约等于15.95
和log10(2^24)
约等于7.22
位,因此 double 的有效数字是15~16
位,float 的有效数字是7~8
位,这些有效位是包含整数部分和小数部分; -
double 的指数部分是 11 位,而 float 的指数位是 8 位,意味着 double 相比 float 能表示更大的数值范围;
-
-
二进制小数,是如何转换成二进制浮点数的呢?
-
因为 IEEE 标准规定,二进制浮点数的小数点左侧只能有 1 位,并且还只能是 1,既然这一位永远都是 1,那就可以不用存起来了。
-
于是就让 23 位尾数只存储小数部分,然后在计算时会自动把这个 1 加上,这样就可以节约 1 位的空间,尾数就能多存一位小数,相应的精度就更高了一点。
-
转回十进制数
-
-
-
-
0.1+0.2==0.3?
结论:在计算机中 0.1 + 0.2 并不等于完整的 0.3。-
主要是因为有的小数无法可以用「完整」的二进制来表示,所以计算机里只能采用近似数的方式来保存,那两个近似数相加,得到的必然也是一个近似数。
-
并不是所有小数都可以用「完整」的二进制来表示的,比如十进制 0.1 在转换成二进制小数的时候,是一串无限循环的二进制数,计算机是无法表达无限循环的二进制数的,毕竟计算机的资源是有限。
-
因此,计算机只能用「近似值」来表示该二进制,那么意味着计算机存放的小数可能不是一个真实值。
-
现在基本都是用 IEEE 754 规范的「单精度浮点类型」或「双精度浮点类型」来存储小数的,根据精度的不同,近似值也会不同。
-