1、 问题的引入首先从一个简单的计算开始。
float a=1.0f;
float b=0.1f;
System.out.println(a-b);
打印出来
0.9
或许你想肯定是0.9,这还用问。其实你被System.out.println欺骗了。再看
用System.out.printf("%1.20f\n",a-b) 打印出来
0.89999997615814210000
这才是实际值,System.out.println隐藏的做了精度四舍五入。
同理System.out.printf("%1.20f\n",0.1f),打印出来
0.10000000149011612000
为什么呢?看到这里,我们应该想到这是float引起的了吧。
2、float在计算机里表示
java中的float和double,采用IEEE754标准,实际上是用利用科学计数法来表达实数。即用一个尾数(Mantissa也叫有效数字 ),一个基数(Base),一个指数(Exponent)以及
一个表示正负的符号来表达实数。实数表示分为三个域。
float用32bit存储,double用64bit存储。
第一个域为符号域,0 表示数值为正数,而 1 则表示负数;
第二个域为指数域,对应于我们之前介绍的二进制科学计数法中的指数部分。其中单精度数为 8 位,双精度数为 11 位。float单精度的指数范围为-127 和 127 之间。
第三个域为尾数域,其中单精度数为 23 位长,双精度数为 52 位长。
造成无法准确的计算出来我们想要的结果,原因是科学计算法无法准确的存储,只有相近的取近似值(看样子,计算机也不太聪明,呵呵)。举例
System.out.printf("%1.10f\n",9.625f);
System.out.printf("%1.10f\n",9.624f);
打印出来
9.6250000000
9.6239995956
3、总结
所以在进行浮点运算的时候,一定要小心。解决办法是用BigDecimal,进行计算之后取精度。
网上也有这种办法计算。
Java中的小数精确计算
public class FloatCalc {
// 默认除法运算精度
private static final int DEF_DIV_SCALE = 10;
/**
* 提供精确的加法运算。
*
* @param v1 * 被数
* @param v2 * 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1 * 被减数
* @param v2 * 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1 * 被乘数
* @param v2 * 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
*
* @param v1 * 被除数
* @param v2 * 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
*
* @param v1 * 被除数
* @param v2 * 除数
* @param scale
* 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v * 需要四舍五入的数字
* @param scale * 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
分享到:
相关推荐
为了克服这个问题,Java提供了`java.math.BigDecimal`类,它提供了一种方法来进行高精度的十进制计算,从而避免浮点运算中的精度问题。 描述中的"Java实现的浮点类的精确计算"很可能就是指一个自定义的工具类,该类...
51单片机基础训练项目之简易计算器.功能:普通整型的加减乘除运算。可由读者自主学习并扩展至浮点运算.zip
这份“Java学习笔记(必看经典).doc”文档将涵盖Java的核心概念和重要知识点,对于初学者和有经验的开发者来说都是宝贵的参考资料。 首先,Java的基础部分通常包括以下几个方面: 1. **Java语法基础**:这是所有...
通过学习和理解这个Java控制台四则运算计算程序源码,开发者可以深入掌握Java语言的基础特性,如数据类型、流程控制、异常处理,以及算法设计和实现,尤其是与解析和计算数学表达式相关的部分。此外,这也是一个实践...
Java学习代码是一个涵盖Java编程语言基础知识的资源集合,旨在帮助初学者或有经验的开发者深入理解Java的核心概念。在这个压缩包中,"corejava"很可能包含了一系列与Java基础语法、面向对象编程、类库和API相关的...
对于浮点型计算,除法运算会自动产生浮点结果,即使两个操作数都是整型。 3. **控制流**:条件语句(if-else)和循环(for, while)是控制程序流程的关键工具。在计算器中,这些结构可能用于检查用户输入的合法性,...
Java学习基础入门是每个想要踏入Java编程世界的学习者必经的阶段。这个教程涵盖了Java语言的基础概念、语法和常用API,对于初学者来说是极好的起点。以下将详细阐述Java学习的一些关键知识点。 1. **Java简介**:...
Java的基础包括数据类型(如整型、浮点型、字符型和布尔型),变量的声明与赋值,以及操作符的使用。其中,Java的封装性、继承性和多态性是面向对象编程的核心特性,是区分它与其他编程语言的重要标志。 课件将详细...
Strictfp修饰的方法必须使用严格的浮点运算,以产生再生结果(满足可移植性)。 4、要得到完全可预测的结果比快速性能更为重要的话,请使用StrictMath类。 5、数字之间的合法转化。P44。 6、布尔值和任何数字类型...
"良葛格java学习笔记"是一份专为初学者设计的Java学习资源,它以通俗易懂的方式阐述了Java编程的基础知识,对于想要踏入Java世界的人来说,是一份非常宝贵的参考资料。 在Java的学习过程中,首先你需要理解其核心...
"J2ME浮点库MathFP" 是一个专为Java Micro Edition (J2ME) 平台设计的浮点数处理库,它提供了对浮点运算的支持,包括基本的小数运算和一些复杂的数学函数。MathFP 库的出现是为了弥补J2ME平台原生对浮点计算支持的...
### Java学习笔记知识点详解 #### 一、类变量与成员变量的区别 - **类变量**:也称为静态变量,使用`static`关键字声明。在整个类的生命周期中只有一个副本,无论创建多少个对象,该变量的副本都只有一份。例如,...
### Java学习总结:C程序员的感悟 #### 第一章:Java入门(C与Java的差异) ##### 基本数据类型: Java的数据类型与C语言相比,在命名上有一定区别,例如整型在C中为`int`,而在Java中也为`int`,但Java的数据...
- **Java虚拟机浮点运算**: 介绍Java虚拟机如何处理浮点数运算,以及与IEEE 754标准的关系。 - **浮点模式**: 描述了Java虚拟机中浮点运算的不同模式及其对精度的影响。 **6. 异常处理** - **异常**: JVM支持异常...
#### 一、Java学习概述 在文档标题《java学习(一).pdf》中,我们了解到这份文档旨在介绍Java的基础学习内容。而在描述部分提到的“java学习笔记(一)”进一步揭示了这是一份关于Java入门学习的笔记资料。这些...
### 逐步深入的Java学习笔记知识点总结 #### 一、Java环境配置 1. **JAVA_HOME**: 配置JDK的目录。这是Java环境的基本配置之一,用于指示系统JDK安装的位置。 - **Linux系统**: ```bash JAVA_HOME=/opt/jdk1.5.0...
《CoreJava学习笔记》 Java,作为一种广泛使用的高级编程语言,以其独特的特性和优势深受开发者喜爱。本学习笔记旨在深入浅出地介绍Java的核心概念,帮助初学者快速掌握这一强大的工具。 1. Java特点 Java语法...
Java编程语言以其强大的功能和广泛的应用领域而闻名,其语法基础是学习Java的基石。SCJP(SUN Certified Programmer for the Java Platform)考试是检验Java程序员语法基础的重要考核,涵盖了许多核心概念,如关键字...