学习java浮点型的一些细节

出自《Java深入解析》的例子

例1、先看一段代码:

public static void main(String[] args) {
double d1 = 0.1;
double d2 = 0.2;
System.out.println("" + d1 + "+" + d2 + "=" + (d1 + d2));
}

初学者可能脱口而出执行的结果是输出 d1+d2=0.3。但是结果却没有这么简单:

0.1+0.2=0.30000000000000004

转念一想,却也没有一点玄妙。

二进制只能表示十进制中诸如0.5,0.25,0.125之类的小数。

十进制中可以表示0.1~0.9的小数,却不能表示1/3这样的分数。以此类推需要表示1/3,可能3进制更能胜任。

例2、BigDecimal是用来表示精度较大的小数的类,用二进制的数据表示十进制数可以说真是强人所难了。

for (int i = 1; i <= 9; i++) {
double d = Double.parseDouble("0."+i);
System.out.println(d);
BigDecimal bd = new BigDecimal(d);
System.out.println(bd);
}

结果:


0.1
0.1000000000000000055511151231257827021181583404541015625
0.2
0.200000000000000011102230246251565404236316680908203125
0.3
0.299999999999999988897769753748434595763683319091796875
0.4
0.40000000000000002220446049250313080847263336181640625
0.5
0.5
0.6
0.59999999999999997779553950749686919152736663818359375
0.7
0.6999999999999999555910790149937383830547332763671875
0.8
0.8000000000000000444089209850062616169452667236328125
0.9
0.90000000000000002220446049250313080847263336181640625

例3.不如做个测试,看看计算机“偏爱”什么样的数字吧。


 1 /**
2 * 测试0.0001~0.9999范围内的小数那些可以被二进制准确表示
3 * */
4 public class FloatStorage {
5
6 public static void main(String[] args) {
7 int limit = 9999;// 测试的范围0.0001-0.9999
8 int length = String.valueOf(limit).length();// 小数的位数
9
10 System.out.println("在0.0001~0.9999之间可以被准确表示的小数有");
11
12 for (int i = 1; i <= 9999; i++) {
13 int significance = String.valueOf(i).length();// 小数的非0数位
14 int zero = length - significance;// 小数的0数位
15 StringBuilder sb = new StringBuilder("0.");// 建立字符串
16 for (int j = 1; j <= zero; j++) {
17 sb.append(0);
18 }
19 sb.append(i);
20 BigDecimal bd = new BigDecimal(Double.parseDouble(sb.toString())/* 得到二进制数 */);
21 if (bd.scale() <= length) {// 如果符合我们的要求,输出
22 System.out.println(bd);
23 }
24 }
25 }
26
27 }

运行结果:


在0.0001~0.9999之间可以被准确表示的小数有
0.0625
0.125
0.1875
0.25
0.3125
0.375
0.4375
0.5
0.5625
0.625
0.6875
0.75
0.8125
0.875
0.9375

真是寥寥无几啊!

如果小结一下浮点数的特点,原来浮点数和小数之间还是有一定的差别,

在赋值或者存储中浮点类型的精度有限,

同时在计算机实际处理和运算过程中,浮点数本质上是以二进制形式存在的。

二进制所能表示的两个相邻的浮点值之间存在一定的间隙,浮点值越大,这个间隙也会越大。

如果此时对较大的浮点数进行操作时,浮点数的精度问题就会产生,甚至出现一些“不正常"的现象。

例4


public class BigFloat {

public static void main(String[] args) {
float f1 = 30000f;
float f2 = f1 + 1;
System.out.println("f1:" + f1);
System.out.println("f2:" + f2);
if (f1 < f2) {
System.out.println("f1<f2 成立");
} else {
System.out.println("f1<f2 不成立");
}

float f3 = 30000000f;
float f4 = f3 + 1;
System.out.println("f3:" + f3);
System.out.println("f4:" + f4);
if (f3 < f3) {
System.out.println("f3<f3 成立");
} else {
System.out.println("f3<f4 不成立");
}
}

}

运行的结果:

f1:30000.0
f2:30001.0
f1<f2 成立
f3:3.0E7
f4:3.0E7
f3<f4 不成立

一个数加一不比原来的数大,这就是由于精度产生的现象了。

时间: 2024-08-29 06:19:24

学习java浮点型的一些细节的相关文章

学习java随笔第八篇:封装、继承、多态

java和c#一样都是面向对象的语言. 面向对象的语言有三大特征:封装.继承.多态 封装 封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别. class Person2 { private String name; public void setName(String name) { this.name=name; } public String getName() { return name; } private String sex; public voi

在线学习Java免费资源推荐

你想学习Java吗?来对地方了!这篇文章将会介绍很多高质量的免费资源,包括网页.论坛.电子书和速查表. Java是一种面向对象的编程语言,拥有独立.多线程.安全.动态和健壮的特点.归功于其多功能的特点,Java已经成为最流行的编程语言之一,可以让你开发出健壮的应用程序. Java几乎是所有商务应用程序的核心.它有多种脚本语言和流行的框架,可以开发客户端和服务端.因此,学习Java不仅仅可以提高你的知识储备,也有利于你在事业上的发展. 这篇文章将介绍各种各样的网络资源(不包含必读的Java书籍),

【转】学习JAVA的步骤

好东西大家分享: JAVA学习的一些重点 . Java语言基础 谈到Java语言基础学习的书籍,大家肯定会推荐Bruce Eckel的<Thinking in Java>.它是一本写的相当深刻的技术书籍,Java语言基础部分基本没有其它任何一本书可以超越它.该书的作者Bruce Eckel在网络上被称为天才的投机者,作者的<Thinking in C++>在1995年曾获SoftwareDevelopment Jolt Award最佳书籍大奖,<Thinking in Jav

学习Java之路

作为一个小白,虽然还只学习了Java的基础特性,但必须明白我们在Java之路上上要怎么走,走哪些路.分享我计划的路线希望大神指正. 第一部分:学习Java基础特性如类的构成:类的分类如接口,子类,抽象类,枚举等类和特殊类,了解他们的作用,多态性质等:还有他的一些关键词static,public,protected和private达到的类对实例的限制.还有类的封装特性,枚举,泛型等.(我现在学习部分) 第二部分:学习数据库,了解他的原理,运算等内容(我现在学习部分) 第三部分:API和GUI:主要

【JAVA学习笔记】-零基础学习JAVA人分享自己的心得(转)

进入毕业季,毕业设计早早的做完,不想那么早进入职场,便趁此大好时光,一边接受企业培训,一遍自学JAVA.在我看来,学习一门语言必备的几个要点在于,看,练,悟.在这个连技术也已经沦为快餐的时代,很多人无可厚非的认为,在短时间内,快速应用一门语言才是他们所追求的,这也造成了当今培训机构的泛滥.我对此不评价,存在既是合理.但是,我这些心得体会,是想对那些真正喜欢技术的朋友,动机纯粹的朋友而言的,那些不喜欢的人,尽管拍砖,嘿嘿. 学习技术的时候,你是否总会被一些琐事烦恼呢,qq,网游,小说... 我并不

[转]在线学习java资料集合

原文链接: fromdev 翻译: ImportNew.com- 赖 信涛译文链接: http://www.importnew.com/11910.html[ 转载请保留原文出处.译者和译文链接.] 本文由 ImportNew - 赖 信涛 翻译自 fromdev.欢迎加入Java小组.转载请参见文章末尾的要求. 你想学习Java吗?来对地方了!这篇文章将会介绍很多高质量的免费资源,包括网页.论坛.电子书和速查表. Java是一种面向对象的编程语言,拥有独立.多线程.安全.动态和健壮的特点.归功

零基础学习java:变 量(一)

一.变量的概念: (1)内存中的一个存储区域 (2)该区域有自己的名称(变量名)和类型(数据类型) (3)Java中每个变量必须先声明,后使用 (4)该区域的数据可以在同一类型范围内不断变化 使用变量注意: (1)变量的作用域:一对{ }之间有效 (2)初始化值 定义变量的格式:数据类型    变量名  =  初始化值 二.变量的分类--按数据类型 对于每一种数据都定义了明确的具体数据类型,在内存中分配了不同大小的内存空间. 1.整数类型:byte.short.int.long Java各整数类

在线学习Java免费资源推荐(来自:importnew)

你想学习Java吗?来对地方了!这篇文章将会介绍很多高质量的免费资源,包括网页.论坛.电子书和速查表. Java是一种面向对象的编程语言,拥有独立.多线程.安全.动态和健壮的特点.归功于其多功能的特点,Java已经成为最流行的编程语言之一,可以让你开发出健壮的应用程序. Java几乎是所有商务应用程序的核心.它有多种脚本语言和流行的框架,可以开发客户端和服务端.因此,学习Java不仅仅可以提高你的知识储备,也有利于你在事业上的发展. 这篇文章将介绍各种各样的网络资源(不包含必读的Java书籍),

学习Java基础的一些收获一(this、static、super、final)

Java语言中This关键字应用浅析 应用一:引用成员变量 public class Student{ //定义一个类,类的名字为student. public Student(){ //定义 一个方法,名字与类相同故为构造方法 this(“luobo”) //这个this就是调用了下面的有参数的构造方法 } public Student(String name){ //定义一个带形式参数的构造方法 } } 如上面这个代码中,有一个成员变量name.同时在方法中有个形式参数,名字也是name.然