问题:
得到的结果如下:
f=2.0015E7
d=2.0015E7
d2=2.0014999E7
从输出结果可以看出double 可以正确的表示20014999 ,而float 没有办法表示20014999
,得到的只是一个近似值。这样的结果很让人讶异。20014999 这么小的数字在float下没办法表示。于是带着这个问题,做了一次关于float和double学习,做个简单分享,希望有助于大家对java 浮点数的理解。
关于
java 的
float 和
double
Java
语言支持两种基本的浮点类型: float 和
double 。java 的浮点类型都依据
IEEE 754 标准。IEEE 754 定义了32
位和 64 位双精度两种浮点二进制小数标准。
IEEE 754
用科学记数法以底数为 2 的小数来表示浮点数。32
位浮点数用 1 位表示数字的符号,用
8 位来表示指数,用 23 位来表示尾数,即小数部分。作为有符号整数的指数可以有正负之分。小数部分用二进制(底数
2 )小数来表示。对于64 位双精度浮点数,用
1 位表示数字的符号,用
11 位表示指数,52 位表示尾数。如下两个图来表示:
float(32位):
double(64位):
都是分为三个部分:
(1) 一个单独的符号位s 直接编码符号s 。
(2)k 位的幂指数E ,移码表示
。
(3)n 位的小数,原码表示
。
那么
20014999
为什么用 float
没有办法正确表示?
结合float和double的表示方法,通过分析
20014999
的二进制表示就可以知道答案了。
以下程序可以得出
20014999
在
double
和
float
下的二进制表示方式。
输出结果如下:
Double:100000101110011000101100111100101110000000000000000000000000000
Float: 1001011100110001011001111001100
对于输出结果分析如下。对于
double
的二进制左边补上符号位
0
刚好可以得到
64
位的二进制数。根据double的表示法,分为符号数、幂指数和尾数三个部分如下:
0
10000010111 0011000101100111100101110000000000000000000000000000
对于
float 左边补上符号位
0 刚好可以得到
32 位的二进制数。
根据float的表示法,
也分为
符号数、幂指数和尾数三个部分如下
:
0
10010111 00110001011001111001100
绿色部分是符号位,红色部分是幂指数,蓝色部分是尾数。
对比可以得出:符号位都是
0 ,幂指数为移码表示,两者刚好也相等。唯一不同的是尾数。
在
double 的尾数为:
001100010110011110010111 0000000000000000000000000000
,省略后面的零,至少需要24位才能正确表示
。
而在
float 下面尾数为:
00110001011001111001100
,共 23
位。
为什么会这样?原因很明显,因为
float尾数 最多只能表示
23 位,所以
24 位的
001100010110011110010111 在
float 下面经过四舍五入变成了
23 位的
00110001011001111001100 。所以
20014999 在
float 下面变成了
20015000 。
也就是说 20014999
虽然是在float的表示范围之内,但 在
IEEE 754 的
float 表示法精度长度没有办法表示出
20014999 ,而只能通过四舍五入得到一个近似值。
总结:
浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用
float 和
double 作精确运算的时候要特别小心。
可以考虑采用一些替代方案来实现。如通过 String 结合
BigDecimal 或者通过使用
long 类型来转换。
分享到:
相关推荐
### Java中的1到20的阶乘 在Java编程语言中,实现1到20的阶乘是一个典型的编程练习,可以帮助初学者理解循环结构、变量声明以及简单的数学运算。本篇文章将详细介绍如何在Java中计算1到20的阶乘,并深入探讨其中...
1. 思考最佳的猜数方案,理论上,最高效的策略是每次猜测中间值,这样最多需要7次就能确定答案。 2. `System.out.println("猜对了!");`放在while循环外面是因为只有在猜对的情况下才结束循环,如果放在循环体内,...
1. **黄金分割数**:使用分层计算法求解高精度黄金分割数,可以练习数值计算和精度控制。 2. **连续数**:这道题涉及数组处理和子序列查找,可以锻炼算法设计和遍历技巧。 3. **幸运数**:幸运数的计算涉及到数学...
- **精度区别:** `float`类型的精度较低,而`double`类型具有更高的精度。 - **表示形式:** 通常以十进制小数的形式表示。 #### 第6课 练习课(一) - **主要内容:** 实践前面章节所学的基础知识。 - **练习示例:*...
1. **Java源程序和字节码**:Java源程序文件的扩展名是`.java`,编译后生成的字节码文件扩展名为`.class`。Java源代码通过Java编译器(javac)转化为字节码,字节码可以在不同平台上运行,这是Java的跨平台特性。 2. ...
- **提升综合能力:** 培养学生的逻辑思维能力、问题解决能力和编程实践能力,同时增强其独立思考与团队合作的能力。 #### 二、实验要求 - **目标功能:** 实现一个具有基本数学运算功能的简易计算器,包括但不限于...
1. Java 语言的三种技术架构: J2EE:企业版,是为开发企业环境下的应用程序提供的一套解决方案。该技术体系中包含的技术如 Servlet、Jsp 等,主要针对 Web 应用程序开发。 J2SE:标准版,是为开发普通桌面和商务...
- **使用陷阱详解**:探讨在使用原始数据类型时可能遇到的问题,比如溢出错误、精度损失等,并提供相应的解决方案。 #### 五、运算符与表达式 - **运算符分类**:介绍算术运算符、关系运算符、逻辑运算符等不同...
1. **编写源代码**:使用文本编辑器(如Notepad、Eclipse、IntelliJ IDEA等)编写Java源代码。每个源文件应该只包含一个`public`类(如果有),并且文件名需与该`public`类的名称相同。 2. **编译源代码**:使用...
(1)容量大的数据类型转换为容量小的数据类型时,要加上强制转换符,但可能造成精度降低或溢出;使用时要格外注意。 (2)有多种类型的数据混合运算时,系统首先自动的将所有数据转换成容量最大的那一种数据类型,...
- 对于浮点数的比较,由于浮点数存在精度误差,因此不能直接使用 `==` 或 `!=` 进行比较。 - 正确的方法是定义一个足够小的误差范围 `EPSILON`,然后使用 `(x >= -EPSILON) && (x )` 来检查浮点数是否接近于零。 - ...
- **符合人类认知习惯**:面向对象编程的方式与人们思考问题的方式一致。 - **代码复用性**:通过继承和多态等机制提高代码的复用性。 - **模块化**:降低模块间的耦合度,提高系统的可维护性和可扩展性。 #### 类...
- 符合人们的思考习惯。 - 将复杂问题简化。 - 让程序员从具体的实现细节中抽离出来,专注于设计解决问题的策略。 - **特征**:待续。 以上是对 Java SE 基础知识的一些总结,涵盖了从 Java 的基本概念到面向...
- 这个时期的电子游戏往往强调玩家的反应速度和策略思考,而非复杂的故事线或高精度的视觉效果。 4. **Java重制80年代游戏的优势**: - 稳定性:Java的强类型和垃圾回收机制可以提高游戏的稳定性和内存管理。 - ...
4. **数值计算与精度控制**:对于涉及大量计算的问题,需要关注浮点数的精度问题,C语言中可以使用高精度库,Java则有BigDecimal类提供支持。 5. **代码组织与设计模式**:良好的代码结构和设计模式可以使代码更易于...
它不仅仅是设计工具,更是艺术家思考和创作的延伸。在这个平台上,无论是绘制简单的几何形状,还是复杂的艺术品,都可以轻松实现。 ORIPA的自动计算功能,是基于先进的数学模型,能够自动计算出最佳的折叠路径。这...