问题

Java(其他编程语言也存在类似问题)中浮点数直接进行算术运算会导致精度丢失。

示例代码:

System.out.println("1.0 - 0.9 =" + (1.0 - 0.9));
System.out.println("0.1 + 0.02 =" + (0.1 + 0.02));
System.out.println("1.013 * 100 =" + (1.013 * 100));
System.out.println("123.3 / 100 =" + (123.3 / 100));

运行结果为:

解决方案

Java提供了BigDecimal类用来解决浮点数的运算。

BigDecimal提供了大量的构造方法用于生成一个BigDecimal对象,包括把基本类型、数字字符串、数字数组构造成BigDecimal对象。

这里以double类型数字转换为BigDecimal对象进行说明。常用有三种方式将double类型数字转换为BigDecimal对象。

  1. BigDecimal(double value):不推荐使用。生成的数值和value是一个近似数,不精确。
  2. BigDecimal(String value):推荐使用。
  3. BigDecimal.valueOf(double value):推荐使用。可以直接把一个double类型数值转换为精确的BigDecimal对象。

BigDecimal类型提供了相应方法实现算术运算,常用方法如下表所示,具体参数可以查询API文档。

方法 方法说明
add() 相加
subtract() 相减
multiply() 相乘
devide() 相除
pow() 幂运算

示例代码:

BigDecimal num1 = new BigDecimal("0.05");
BigDecimal num2 = new BigDecimal("0.01");
System.out.println("0.05 + 0.01 =" + (num1.add(num2)));
System.out.println("0.05 - 0.01 =" + (num1.subtract(num2)));
System.out.println("0.05 * 0.01 =" + (num1.multiply(num2)));
System.out.println("0.05 / 0.01 =" + (num1.divide(num2)));

  

运行结果:

自定义浮点数计算类

项目中如果要频繁进行浮点数计算,可以自定义一个浮点数计算类。

在进行除法运算过程中,如果需要进行精度控制,可以使用divide(BigDecimal divisor, int scale, int roundingMode)方法进行精度控制。sacale表示精度,roundingMode表示舍入方式。

示例代码:

public class MyArith {
/** 定义除法运算精度 */
private static final int DEFAULT_DIV_SCALE = 10; /** 单例模式 */
private MyArith() {
} /** 精确加法运算 */
public static double add(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.add(b2).doubleValue();
} /** 精确加法运算 */
public static double sub(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.subtract(b2).doubleValue();
} /** 精确乘法运算 */
public static double mul(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.multiply(b2).doubleValue();
} /** 精确除法运算 */
public static double div(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
// 精确到小数点后10位,四舍五入
return b1.divide(b2, DEFAULT_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
} /** 测试方法 */
public static void main(String[] args) {
System.out.println("0.05 + 0.01 = " + MyArith.add(0.05, 0.01));
System.out.println("1.0 + 0.42 = " + MyArith.sub(1.0, 0.42));
System.out.println("4.015 * 100 = " + MyArith.mul(4.015, 100));
System.out.println("123.3 / 99 = " + MyArith.div(123.3, 99)); }
}

  

运行结果:

最新文章

  1. 信息安全系统设计基础exp_5
  2. 【leetcode】Combination Sum
  3. Go语言学习资源
  4. 【转】Problems with HTTPS, HttpWebRequest, and iOS?
  5. ORA-01000:超出打开游标的最大数(C#)
  6. POJ3020——Antenna Placement(二分图的最大匹配)
  7. online ddl 跟踪
  8. 代码-Weka的LinearRegression类
  9. 关于如何设置reduce的个数
  10. Android自定义垂直滚动自动选择日期控件
  11. Response.Write 、RegisterClientScriptBlock和RegisterStartupScript总结
  12. Python django实现简单的邮件系统发送邮件功能
  13. seq2seq-chatbot:200 行代码实现聊天机器人
  14. python检测变量是否有定义(即使用前检查是否定义好)
  15. (转载)JSON.stringfy()和JSON.parse()的作用
  16. [转]GitHub上优秀的Go开源项目
  17. Bootstrap3基础 btn-primary/warning... 三类按钮的六种样式
  18. What is the difference between WinRT, UWP and WPF?
  19. iOS邮箱、手机号等常用验证功能 判断字符串是否int float
  20. [转]C#如何判断操作系统位数是32位还是64位

热门文章

  1. 一些好用的Linux命令组合
  2. linux中目录操作<1>
  3. bzoj 4446: [Scoi2015]小凸玩密室【树形dp】
  4. bzoj 4010: [HNOI2015]菜肴制作【拓扑排序】
  5. IO流案例:1.复制多级文件夹 2.删除多级文件夹
  6. 自适应的两端对齐:text-align:justify
  7. Python实现两已知排好序的列表合并成一个排好序的列表
  8. 2017年“嘉杰信息杯” 中国大学生程序设计竞赛全国邀请赛 Highway
  9. 贪心 HDOJ 5090 Game with Pearls
  10. 1. Visio Web 形状 - 无法与 Web 服务器建立连接。请稍后重新进行搜索。处理方式