[计算机基础] --- 浮点数的存储以及使用注意

简介: [计算机基础] --- 浮点数的存储以及使用注意

1. 浮点数转换二进制

在进行浮点数转二进制之前,先回顾下整数转二进制如何进行的?

把10进制下123转为2进制,得到1111011(2)

小数转二进制:

10进制下0.71875转为2进制为0.10111

0.71875 * 2 = 1.4375 得到1

0.4375 * 2 = 0.875 得到0

0.875 * 2 = 1.75 得到1

0.75 * 2 = 1.5 得到1

0.5 * 2 = 1.0 得到1

于是得到0.10111

2. 浮点数在计算机中是如何表示的

2.1 IEEE754标准

IEEE754标准提供了浮点数在计算机内存中的存储标准,即以二进制的方式存储十进制浮点数。

浮点数在计算机中的存储方式遵循IEEE 754 浮点数计数标准,可以表示为:

采用尾数 + 阶码的编码方式,更通俗一点说,就是类似于数学课本上所学的科学计数法表示方式:有效数字 + 指数位!

因此,只要给出:符号(S)、阶码部分(E)、尾数部分(M) 这三个维度的信息,一个浮点数的表示就完全确定下来了,所以float和double这两种类型的浮点数在计算机中的存储结构就表示成下图所示这个样子:

  • 符号位(s):0-正 1-负
  • 阶码部分(E)(指数部分):
    对于float型浮点数,指数部分8位,考虑可正可负,因此可以表示的指数范围为-127 ~ 128
    对于double型浮点数,指数部分11位,考虑可正可负,因此可以表示的指数范围为-1023 ~ 1024
  • 尾数部分(M):
    浮点数的精度是由尾数的位数来决定的:
    对于float型浮点数,尾数部分23位,换算成十进制就是 2^23=8388608,所以十进制精度只有6 ~ 7位;
    对于double型浮点数,尾数部分52位,换算成十进制就是 2^52 = 4503599627370496,所以十进制精度只有15 ~ 16位

2.2 浮点数转换为IEEE754标准示例

float 6.36 = 110.01011100…

1> 转换为IEEE574标准表示: 1.10010111000… x 2^2

2> 对应可得:

  • 符号位:0
  • 阶码部分:127+2 = 129 = 1000 0001
  • 尾数部分:1001011100…,其实它本身无限不循环,但若以float型精度来截取23位,则可以表示为10010111000010100011111
    3> 因此最终的总结果为(以32位精度float表示):
    01000000110010111000010100011111

3. 浮点数使用注意

先看现象

涉及诸如float或者double这两种浮点型数据的处理时,偶尔总会有一些怪怪的现象,不知道大家注意过没,举几个常见的栗子:

典型现象(一):条件判断超预期

System.out.println( 1f == 0.9999999f );   // 打印:false
System.out.println( 1f == 0.99999999f );  // 打印:true    纳尼?

典型现象(二):数据转换超预期

float f = 1.1f;
double d = (double) f;
System.out.println(f);  // 打印:1.1
System.out.println(d);  // 打印:1.100000023841858  纳尼?

典型现象(三):基本运算超预期

System.out.println( 0.2 + 0.7 );  
// 打印:0.8999999999999999   纳尼?

典型现象(四):数据自增超预期

float f1 = 8455263f;
for (int i = 0; i < 10; i++) {
    System.out.println(f1);
    f1++;
}
// 打印:8455263.0
// 打印:8455264.0
// 打印:8455265.0
// 打印:8455266.0
// 打印:8455267.0
// 打印:8455268.0
// 打印:8455269.0
// 打印:8455270.0
// 打印:8455271.0
// 打印:8455272.0
float f2 = 84552631f;
for (int i = 0; i < 10; i++) {
    System.out.println(f2);
    f2++;
}
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?
//    打印:8.4552632E7   纳尼?不是 +1了吗?

看到没,这些简单场景下的使用情况都很难满足我们的需求,所以说用浮点数(包括double和float)处理问题有非常多隐晦的坑在等着咱们!

导致这些的原因都是精度的问题。

相关文章
|
数据可视化 数据挖掘 Python
【数据分析与可视化】Matplotlib中动态rc参数设置详解与实战(图文解释 附源码)
【数据分析与可视化】Matplotlib中动态rc参数设置详解与实战(图文解释 附源码)
1252 0
|
存储 算法 固态存储
【计算机组成原理】存储系统
【计算机组成原理】存储系统
7941 0
【计算机组成原理】存储系统
|
XML Java Android开发
Android Studio App开发之翻页视图ViewPager的讲解及实战(附源码 包括翻页视图和翻页标签栏)
Android Studio App开发之翻页视图ViewPager的讲解及实战(附源码 包括翻页视图和翻页标签栏)
1711 0
|
10月前
|
存储 缓存 Kubernetes
KubeCon China 2025 速递:成本 vs 性能,如何为 K8s 工作流选型最佳存储方案?
本文基于KubeCon China 2025的精彩议题分享,探讨在成本约束下为K8s工作流选择最佳存储方案。
|
存储 算法
pid控制
这篇文章详细介绍了PID控制算法的理论基础、组成部分、不同形式的算法(位置式和增量式PID),以及参数调试的步骤和技巧,旨在帮助读者理解和应用PID控制器进行有效的系统控制。
1717 2
pid控制
|
数据采集 JavaScript 搜索推荐
服务器端渲染(SSR)(Nuxt+Next.js)
服务器端渲染(SSR)技术在服务器上生成页面HTML,提升首屏加载速度和SEO效果。Nuxt.js和Next.js分别是基于Vue.js和React.js的流行SSR框架。Nuxt.js提供自动化路由管理、页面级数据获取和布局系统,支持SSR和静态站点生成。Next.js支持SSR、静态生成和文件系统路由,通过`getServerSideProps`和`getStaticProps`实现数据获取。SSR的优点包括首屏加载快、SEO友好和适合复杂页面,但也会增加服务器压力、开发限制和调试难度。选择框架时,可根据项目需求和技术栈决定使用Nuxt.js或Next.js。
|
存储 监控 安全
如何实施有效的网络安全策略?
【10月更文挑战第13天】如何实施有效的网络安全策略?
872 5
|
Kubernetes Cloud Native 微服务
微服务实践之使用 kube-vip 搭建高可用 Kubernetes 集群
微服务实践之使用 kube-vip 搭建高可用 Kubernetes 集群
682 1
|
开发框架 前端开发 JavaScript
在DevExpress的GridView的列中,动态创建列的时候,绑定不同的编辑处理控件
在DevExpress的GridView的列中,动态创建列的时候,绑定不同的编辑处理控件
|
存储 数据管理 Linux
Linux命令reposync详解
`reposync`是Linux的命令行工具,用于同步远程YUM仓库到本地,便于离线部署和更新软件。它从远程索引中识别新、改、删包,下载到指定目录,支持配置文件、多参数定制,如`-c`指定配置,`-r`选择仓库,`-p`设定下载路径。`-n`仅同步最新包,`-q`减少输出。最佳实践包括定时同步、验证GPG签名和使用HTTPS。注意网络稳定性、磁盘空间及索引备份。

热门文章

最新文章