目录
注:所有的[斜体]内容都是本人自己杜撰的概念,只代表个人理解,可能不能与科学规范的学术概念相吻合
所有的{ }包含的是一个格式
所有的" "包含的是一个对象实体
前言
从一个简单的程序里发现了点蹊跷
float a = 2.0e20+1.0;
float b = a - 2.0e20;
printf("%a",b);
┌──(ivaldi㉿kali)-[~/Desktop/C/float]
└─$ cd "/home/ivaldi/Desktop/C/float/" && gcc main.c -o main && "/home/ivaldi/Desktop/C/float/"main
0x1.d29cfp+41
基础知识
十进制浮点数与二进制浮点数的转换
首先抛开计算机存储的限制,我们来看看如何把一个[十进制浮点数]转化为一个[二进制浮点数]:
0.分离[十进制浮点数]为[符号位]和[不带符号位的十进制浮点数],这个[符号位]与[二进制浮点数]中所包含的[符号位]相同
1.分离[不带符号位的十进制浮点数]为[不带符号位的十进制浮点数的整数部分]和[不带符号位的十进制浮点数的小数部分]
2.[不带符号位的十进制数的整数部分]采用"除以2取余数,倒序相加"的方法,转化为[不带符号位的二进制数的整数部分]
3.[不带符号位的十进制数的小数部分]采用"乘以2取整数,顺序相加"的方法,转化为[不带符号位的二进制数的小数部分]
4.按照{[符号位]+[不带符号位的二进制数的整数部分]+[小数点] "."+[不带符号位的二进制数的小数部分]}的格式拼接在一起就变成了[二进制浮点数]
下面是一个简单的例子:
[十进制浮点数] "-4.8125" 转化为 [二进制浮点数]
(0)[十进制浮点数] "-4.8125" 分成 [符号位] "-" 和 [不带符号位的十进制浮点数] "4.8125"
(1)[不带符号位的十进制浮点数] "4.8125" 分成 [不带符号位的十进制浮点数的整数部分] "4和[不带符号位的十进制浮点数的小数部分] "0.8125"
(2)[不带符号位的十进制浮点数的整数部分] "4" 转化为[不带符号位的二进制数的整数部分] "100"
4 除以 2 = 2 ...... 0
2 除以 2 = 1......0
1 除以 2 = 0......1
得到商为0就没必要继续除了,如果继续除,得到的商和余数都是0,就进入无限循环了
把依次得到的余数,按照倒序,连接在一起,变成"100",这就是[不带符号位的二进制数的整数部分]的结果
(3)[不带符号位的十进制浮点数的小数部分] "0.8125" 转化为[不带符号位的二进制数的小数部分] "1101"
0.8125 乘以 2 = 0.625 + 1
0.625 乘以 2 = 0.25 + 1
0.25 乘以 2 = 0.5 + 0
0.5 乘以 2 = 0.0 + 1
得到小数部分为0就没必要继续乘了,如果继续乘,得到的积都是0,就进入无限循环了
把依次得到的整数部分,按照顺序,连接在一起,变成"1101",这就是[不带符号位的二进制数的小数部分]的结果
(4)按照{[符号位] "-" +[不带符号位的二进制数的整数部分] "100"+[小数点] "."+[不带符号位的二进制数的小数部分] "1101"}的格式,拼接在一起,就变成了[二进制浮点数]"-100.1101",当然,这也可以表示为"-1.001101*"
十六进制数浮点数
[十六进制数浮点数]是[二进制浮点数]的另一种表达形式,差别在于:
- ANSI-C中支持[十进制浮点数]格式的浮点型常量的书写,但是不支持[二进制浮点数]格式的浮点型常量的书写
- [二进制浮点数]只是计算机硬件层面的一种表现方式和原理体现
- C99标准中新增加了对[十六进制数浮点数]格式的浮点型常量的书写的支持
- [十六进制数浮点数]本质还是[二进制浮点数],只是[二进制浮点数]的另一种表达形式
将一个[二进制浮点数]转化为[十六进制数浮点数]的步骤:
0.将[二进制浮点数]拆解成[符号位]+[不带符号位的二进制浮点数]
1.将[不带符号位的二进制浮点数]拆解成[不带符号位的二进制浮点数的整数部分]+[小数点]+[不带符号位的二进制浮点数的小数部分]
2.[不带符号位的二进制浮点数的整数部分]从右往左,每4个一组,不足补0,转化为十六进制数,变成[不带符号位的十六进制数浮点数的整数部分]
3.[不带符号位的二进制浮点数的小数部分]从左往右,每4个一组,不足补0,转化为十六进制数,变成[不带符号位的十六进制数浮点数的小数部分]
4.按照{[十六进制前缀]+[符号位] +[不带符号位的十六进制数浮点数的整数部分]+[小数点]+[不带符号位的十六进制数浮点数的小数部分]}的格式,合成[十六进制数浮点数]
还是上面那个简单的例子:
"-100.1101" -> "-"+"100"+"."+"1101" -> "-"+"0100"+"."+"