首先看如下代码示例:
System.out.println(0.05 + 0.01); System.out.println(0.05 - 0.03); System.out.println(1.025 * 100); System.out.println(305.1 / 1000);
输出结果为:
0.060000000000000005
0.020000000000000004
102.49999999999999
0.30510000000000004
Java语言支持两种基本的浮点类型:float和double,以及与它们对应的包装类Float和Double。它们都依据IEEE 754 标准,该标准为 32 位浮点和 64 位双精度浮点二进制小数定义了二进制标准。
IEEE 754 用科学记数法以底数为 2 的小数来表示浮点数。IEEE 浮点数用 1 位表示数字的符号,用 8 位来表示指数,用 23 位来表示尾数,即小数部分,作为有符号整数的指数可以有正负之分,小数部分用二进制(底数 2)小数来表示
不要用浮点值表示精确值
一些非整数值(如几美元和几美分这样的小数)需要很精确。浮点数不是精确值,所以使用它们会导致舍入误差。因此,使用浮点数来试图表示象货币量这样的精确数量不是一个好的想法。使用浮点数来进行美元和美分计算会得到灾难性的后果。浮点数最好用来表示象测量值这类数值,这类值从一开始就不怎么精确。
使用BigDecimal
从 JDK 1.3 起,Java 开发人员就有了另一种数值表示法来表示非整数: BigDecimal 。 BigDecimal 是标准的类,在编译器中不需要特殊支持,它可以表示任意精度的小数,并对它们进行计算。
用于加、减、乘和除的方法给 BigDecimal 值提供了算术运算。由于 BigDecimal 对象是不可变的,这些方法中的每一个都会产生新的 BigDecimal 对象。因此,因为创建对象的开销, BigDecimal 不适合于大量的数学计算,但设计它的目的是用来精确地表示小数。如果您正在寻找一种能精确表示如货币量这样的数值,则 BigDecimal 可以很好地胜任该任务。
构造 BigDecimal 数
对于 BigDecimal ,有几个可用的构造函数。其中一个构造函数以双精度浮点数作为输入,另一个以整数和换算因子作为输入,还有一个以小数的 String 表示作为输入。要小心使用 BigDecimal(double) 构造函数,因为如果不了解它,会在计算过程中产生舍入误差。请使用基于整数或 String 的构造函数。
public class Test {
public static void main(String[] args) {
// 以双精度浮点数进行构造
BigDecimal bd1 = new BigDecimal(0.5);
BigDecimal bd2 = new BigDecimal(0.1);
System.out.println(bd1.add(bd2));
// 以String类型进行构造
BigDecimal bd3 = new BigDecimal("0.5");
BigDecimal bd4 = new BigDecimal("0.1");
System.out.println(bd3.add(bd4));
}
}
输出结果为:
0.6000000000000000055511151231257827021181583404541015625
0.6
上面代码分别以
BigDecimal(double val) BigDecimal(String val)
不同的方式进行构造 BigDecimal 数,输出的结果是不一样的。
回到最开始的示例,提供工具类进行精确的浮点数运算,包括加减乘除和四舍五入。
import java.math.BigDecimal;
public class ArithUtil {
private static final int DEF_DIV_SCALE = 6; // 默认除法运算精度
/**
* 提供精确的加法运算。
*
* @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 程序中使用浮点数和小数充满着陷阱。浮点数和小数不象整数一样“循规蹈矩”,不能假定浮点计算一定产生整型或精确的结果,虽然它们的确“应该”那样做。最好将浮点运算保留用作计算本来就不精确的数值,譬如测量。如果需要表示定点数(譬如,几美元和几美分),则使用 BigDecimal 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Java
# BigDecimal高精度计算
# 高精度计算
# Java BigDecimal除法精度和格式化输出方式
# 详解java中BigDecimal精度问题
# Java用BigDecimal类解决Double类型精度丢失的问题
# Java中BigDecimal精度和相等比较的坑
# java中double转化为BigDecimal精度缺失的实例
# Java中BigDecimal除法使用不当导致精度问题
# 浮点
# 浮点数
# 四舍五入
# 这类
# 几位
# 如果您
# 很好
# 加减乘除
# 不需要
# 就不
# 两种
# 会在
# 请使用
# 还有一个
# 有几个
# 循规蹈矩
# 它可以
# 并对
# 不了解
# 其中一个
相关文章:
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
企业网站制作公司网页,推荐几家专业的天津网站制作公司?
实例解析angularjs的filter过滤器
建站之星导航菜单设置与功能模块配置全攻略
湖州网站制作公司有哪些,浙江中蓝新能源公司官网?
如何在IIS中新建站点并解决端口绑定冲突?
PHP 500报错的快速解决方法
javascript中的try catch异常捕获机制用法分析
上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?
h5网站制作工具有哪些,h5页面制作工具有哪些?
巅云智能建站系统:可视化拖拽+多端适配+免费模板一键生成
建站之星免费模板:自助建站系统与智能响应式一键生成
如何在IIS服务器上快速部署高效网站?
如何高效利用亚马逊云主机搭建企业网站?
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
一键网站制作软件,义乌购一件代发流程?
文字头像制作网站推荐软件,醒图能自动配文字吗?
如何用西部建站助手快速创建专业网站?
制作网站外包平台,自动化接单网站有哪些?
,如何利用word制作宣传手册?
沈阳制作网站公司排名,沈阳装饰协会官方网站?
微信小程序 五星评分(包括半颗星评分)实例代码
临沂网站制作企业,临沂第三中学官方网站?
如何选购建站域名与空间?自助平台全解析
如何在万网自助建站平台快速创建网站?
代购小票制作网站有哪些,购物小票的简要说明?
定制建站如何定义?其核心优势是什么?
建站之星24小时客服电话如何获取?
制作旅游网站html,怎样注册旅游网站?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
如何选择高效响应式自助建站源码系统?
如何通过老薛主机一键快速建站?
建站之星如何快速更换网站模板?
想学网站制作怎么学,建立一个网站要花费多少?
公司网站的制作公司,企业网站制作基本流程有哪些?
,巨量百应是干嘛的?
建站之星如何修改网站生成路径?
高防服务器如何保障网站安全无虞?
头像制作网站在线制作软件,dw网页背景图像怎么设置?
活动邀请函制作网站有哪些,活动邀请函文案?
如何零基础开发自助建站系统?完整教程解析
北京网站制作公司哪家好一点,北京租房网站有哪些?
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
建站之星安装步骤有哪些常见问题?
linux top下的 minerd 木马清除方法
网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?
定制建站哪家更专业可靠?推荐榜单揭晓
建站主机空间推荐 高性价比配置与快速部署方案解析
如何选择域名并搭建高效网站?
青岛网站设计制作公司,查询青岛招聘信息的网站有哪些?
*请认真填写需求信息,我们会在24小时内与您取得联系。