前言
- 闲来无事便对浮点数进行了探讨,查阅了一些文章并进行了上机测试
话不多说我们一起来看看
提示:以下是本篇文章正文内容,下面案例可供参考
一、什么是浮点数?
- 浮点数即是计算机世界中小数的说法
电气和电子工程师协会IEEE对于计算机浮点数的存储、运算、表示等推出了IEEE754标准
- 标准中规定:
- float32位单精度浮点数在机器中表示用 1 位表示数字的符号,用 8 位表示指数,用 23 位表示尾数。
- double64位双精度浮点数,用 1 位表示符号,用 11 位表示指数,52 位表示尾数。
二、浮点数的存取规则
-
规范化的指数形式
- 如实数 3141.5926 可表示为3.1415926E+3
-
移码
- 移码是真值补码的符号位取反,一般用作浮点数的阶码,目的是便于浮点数运算时的对阶操作
- --------存储浮点数时,会根据其指数加上移码作为其指数域的值
- 移码是真值补码的符号位取反,一般用作浮点数的阶码,目的是便于浮点数运算时的对阶操作
-
举例
- 比如 == 【12.34的单精度浮点数表示】 ==
-
首先将12.34转成二进制
-
整数部分12的二进制是: 1100
>.整数部分转二进制 '除2取余' 小数部分 '乘2取整' 这里不过多赘述
-
小数部分0.34的二进制是: 0.01010111000010100011[1101…]
-
12.34的二进制代码就是: 1100.01010111000010100011[1101…]E+0
>.由于单精度浮点数尾数只有23位,所以需要舍入
-
正规化后再舍入就是: 1.10001010111000010100100E+3
-
其尾数部分即: 10001010111000010100100 \color{blue}{10001010111000010100100} 10001010111000010100100
-
指数为 3 加上移码 127 等于130,其指数域也就是: 1000 \color{00FF00}{1000} 1000 0010 \color{00FF00}{0010} 0010
-
12.34是正数,所以符号位为 0 \color{red}{0} 0
-
综上所述, 12.34的单精度浮点数表示为:
0100 0001 0100 0101 0111 0000 1010 0100
>.上色以区分各个域
0 \color{red}{0} 0 100 \color{00FF00}{100} 100 0001 \color{#00FF00}{0001} 0001 0 \color{#00FF00}{0} 0 100 \color{blue}{100} 100 0101 \color{blue}{0101} 0101 0111 \color{blue}{0111} 0111 0000 \color{blue}{0000} 0000 1010 \color{blue}{1010} 1010 0100 \color{blue}{0100} 0100
-
- 比如 == 【12.34的单精度浮点数表示】 ==
三、上机验证
- 我们来实战证明, 请看代码:
#include <iostream>
using namespace std;
int main()
{
float test=12.34f;
// 这里不直接打印test 是因为编译器编译时会做一些操作(浮点打印整型 就只取整数部分)
printf("%d\n",*(int*)&test);//取地址得到地址 再强转为 int* 再解指针 得到原始值
}
运行后得到 1095069860 这样的"垃圾值", 但是不慌我们放到计算器里看它的二进制值:
哇塞😁 amazing !
四、误差
- 上面例子尾数部分转二进制的计算是算不尽的
- 它的精度取决于存储容器的容量,比如上面32位的float.在后面边界处做了舍入
- 如上面12.34的二进制做还原操作的话得到的会是 12.3399999…
- 这就意味着存取之间可能会存在误差.
- 那么在用到浮点数的程序设计中要特别注意机器误差的累积
.再深入就太复杂了🤣鄙人能力有限有需要可以参考下面的文章
小程序与参考文章
总结
IEEE Floating Point Design is awesome !