BigDecimal类

对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作。BigDecimal类的常用方法如表11-15所示。

表11-15 BigDecimal类的常用方法

序号

方    法

类型

描    述

1

public BigDecimal(double val)

构造

将double表示形式转换

为BigDecimal

2

public BigDecimal(int val)

构造

将int表示形式转换为

BigDecimal

3

public BigDecimal(String val)

构造

将字符串表示

形式转换为BigDecimal

4

public BigDecimal add(BigDecimal augend)

普通

加法

5

public BigDecimal subtract(BigDecimal
subtrahend)

普通

减法

6

public BigDecimal multiply(BigDecimal
multiplicand)

普通

乘法

7

public BigDecimal divide(BigDecimal
divisor)

普通

除法

范例:进行四舍五入的四则运算

    package org.lxh.demo11.numberdemo;
import java.math.BigDecimal;
class MyMath {
public static double add(double d1, double d2)
{ // 进行加法运算
BigDecimal b1 = new BigDecimal(d1);
BigDecimal b2 = new BigDecimal(d2);
return b1.add(b2).doubleValue();
}
public static double sub(double d1, double d2)
{ // 进行减法运算
BigDecimal b1 = new BigDecimal(d1);
BigDecimal b2 = new BigDecimal(d2);
return b1.subtract(b2).doubleValue();
}
public static double mul(double d1, double d2)
{ // 进行乘法运算
BigDecimal b1 = new BigDecimal(d1);
BigDecimal b2 = new BigDecimal(d2);
return b1.multiply(b2).doubleValue();
}
public static double div(double d1,
double d2,int len) {// 进行除法运算
BigDecimal b1 = new BigDecimal(d1);
BigDecimal b2 = new BigDecimal(d2);
return b1.divide(b2,len,BigDecimal.
ROUND_HALF_UP).doubleValue();
}
public static double round(double d,
int len) { // 进行四舍五入
操作
BigDecimal b1 = new BigDecimal(d);
BigDecimal b2 = new BigDecimal(1);
// 任何一个数字除以1都是原数字
// ROUND_HALF_UP是BigDecimal的一个常量,
表示进行四舍五入的操作
return b1.divide(b2, len,BigDecimal.
ROUND_HALF_UP).doubleValue();
}
}
public class BigDecimalDemo01 {
public static void main(String[] args) {
System.out.println("加法运算:" +
MyMath.round(MyMath.add(10.345,
3.333), 1));
System.out.println("乘法运算:" +
MyMath.round(MyMath.mul(10.345,
3.333), 3));
System.out.println("除法运算:" +
MyMath.div(10.345, 3.333, 3));
System.out.println("减法运算:" +
MyMath.round(MyMath.sub(10.345,
3.333), 3));
}
}

BigDecimal是Java中用来表示任意精确浮点数运算的类,在BigDecimal中,使用unscaledValue × 10-scale来表示一个浮点数。其中,unscaledValue是一个BigInteger,scale是一个int。从这个表示方法来看,BigDecimal只能标识有限小数,不过可以表示的数据范围远远大于double,在实际应用中基本足够了。

下面提一下两个精度问题:
 
问题一:BigDecimal的精度问题(StackOverflow上有个家伙问了相关的问题
System.out.println(new BigDecimal(0.1).toString()); // 0.1000000000000000055511151231257827021181583404541015625
System.out.println(new BigDecimal("0.1").toString()); // 0.1
System.out.println(new BigDecimal(
Double.toString(0.1000000000000000055511151231257827021181583404541015625)).toString());// 0.1
System.out.println(new BigDecimal(Double.toString(0.1)).toString()); // 0.1

分析一下上面代码的问题(注释的内容表示此语句的输出)

第一行:事实上,由于二进制无法精确地表示十进制小数0.1,但是编译器读到字符串"0.1"之后,必须把它转成8个字节的double值,因此,编译器只能用一个最接近的值来代替0.1了,即0.1000000000000000055511151231257827021181583404541015625。因此,在运行时,传给BigDecimal构造函数的真正的数值是0.1000000000000000055511151231257827021181583404541015625。
第二行:BigDecimal能够正确地把字符串转化成真正精确的浮点数。
第三行:问题在于Double.toString会使用一定的精度来四舍五入double,然后再输出。会。Double.toString(0.1000000000000000055511151231257827021181583404541015625)输出的事实上是"0.1",因此生成的BigDecimal表示的数也是0.1。
第四行:基于前面的分析,事实上这一行代码等价于第三行
 
结论:
1.如果你希望BigDecimal能够精确地表示你希望的数值,那么一定要使用字符串来表示小数,并传递给BigDecimal的构造函数。
2.如果你使用Double.toString来把double转化字符串,然后调用BigDecimal(String),这个也是不靠谱的,它不一定按你的想法工作。
3.如果你不是很在乎是否完全精确地表示,并且使用了BigDecimal(double),那么要注意double本身的特例,double的规范本身定义了几个特殊的double值(Infinite,-Infinite,NaN),不要把这些值传给BigDecimal,否则会抛出异常。
 
问题二:把double强制转化成int,难道不是扔掉小数部分吗?
int x=(int)1023.99999999999999; // x=1024为什么?

原因还是在于二进制无法精确地表示某些十进制小数,因此1023.99999999999999在编译之后的double值变成了1024。

所以,把double强制转化成int确实是扔掉小数部分,但是你写在代码中的值,并不一定是编译器生成的真正的double值。
验证代码:
double d = 1023.99999999999999;
int x = (int) d;
System.out.println(new BigDecimal(d).toString()); // 1024
System.out.println(Long.toHexString(Double.doubleToRawLongBits(d))); // 4090000000000000
System.out.println(x); //

前面提过BigDecimal可以精确地把double表示出来还记得吧。

我们也可以直接打印出d的二进制形式,根据IEEE 754的规定,我们可以算出0x4090000000000000=(1024)。

BigDecimal and double的更多相关文章

  1. Java浮点数float,bigdecimal和double精确计算的精度误差问题总结

    (转)Java浮点数float,bigdecimal和double精确计算的精度误差问题总结 1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结 ...

  2. java 金额计算,商业计算 double不精确问题 BigDecimal,Double保留两位小数方法

    解决办法================== http://blog.javaxxz.com/?p=763 一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法 进行精 ...

  3. MySQL中Decimal类型和Float Double的区别 & BigDecimal与Double使用场景

    MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形 ...

  4. java bigDecimal and double

    Java BigDecimal和double   BigDecimal是Java中用来表示任意精确浮点数运算的类,在BigDecimal中,使用unscaledValue × 10-scale来表示一 ...

  5. java中如何使用BigDecimal使得Double类型保留两位有效数字

    一.场景:从数据表中读出Decimal类型的数据直接塞给Double类型的对象时,并不会有什么异常. 如果要再此基础上计算,就会发生异常. 比如:读出数据为0.0092,将其乘以100,则变成了0.9 ...

  6. How to convert BigDecimal to Double in spring-data-mongodb framework

    问题描述:我们都知道对于涉及钱的数据必须使用BigDecimal类型进行存储,今天在查询mongo时仍然有精度问题,虽然我在代码中使用了Big Decimal类型,但mongo中使用的是double类 ...

  7. BigDecimal 与double 转化失真

    1.BigDecimal(double val): 失真, 不要使用 BigDecimal(0.1)的值是: 0.1000000000000000055511151231257827021181583 ...

  8. 关于BigDecimal 和 double 类型保存金钱,以及精度问题,银行家舍入法

    1. BigDecimal 类型数据 的创建,构造函数 有 public BigDecimal(BigInteger intVal, long val, int scale, int prec); p ...

  9. Java BigDecimal和double

    BigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数 ...

  10. Java 中浮点数---------BigDecimal和double(初探)

    为什么要使用 bigdecimal? 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了 ...

随机推荐

  1. linux抢占式调度

    为什么会发生调度?   因为cpu是有限的,而操作系统上的进程很多,所以操作系统需要平衡各个进程的运行时间 比如说有的进程运行时间已经很长了,已经占用了cpu很长时间了,这个时候操作系统要公平 就会换 ...

  2. ASP.NET Core MVC 视图

    ASP.NET Core MVC中视图的知识和ASP.NET MVC有很多相似之处,学习难度较低.以下内容主要体现了编程中模块化的思想,模块化才应是我们关注的重点. Layout 布局用于提供各个页面 ...

  3. MySQL学习基础之一 — 数据库查询

    廖大神的练手神器:在线SQL: https://www.liaoxuefeng.com/wiki/1177760294764384/1179611432985088 运行MySQL等实际的数据库软件, ...

  4. UVA - 1330 City Game

    InputThe rst line of the input le contains an integer K | determining the number of datasets. Next l ...

  5. 有关xerosploit运行报错问题的有效解决方案

    [安装xerosploit]安装xerosploit的步骤如下,我是将xerosploit直接克隆到了根目录下(使用“cd /”到达根目录) git clone https://github.com/ ...

  6. MySQL server has gone away和Maximum execution time of 120 seconds exceeded

    今天在写采集时碰到两个问题1.MySQL server has gone away2.Maximum execution time of 120 seconds exceeded 采集程序写好运行大概 ...

  7. Maven配置及使用总结

    一. 安装Maven 1. Maven官网 http://maven.apache.org/ 2. 本例子下载最新的版本,apache-maven-3.3.9 解压后目录描述: bin 含有maven ...

  8. JSPs only permit GET POST or HEAD的解决方案(REST风格)

    问题:原文链接 https://blog.csdn.net/tiberroot/article/details/76615727 看到很多人解决办法使用 @ResponseBody注解 这个意思是按照 ...

  9. 关于EasyML的使用

    一.安装IntelliJ Idea 具体安装过程比较简单.但是遇到一个问题,如今LInux版本的IntelliJ的安装需要jdk1.8及以上版本的支持,但是EasyML目前仅支持jdk1.7的环境. ...

  10. @Primary 使用

    造轮子的一个小小的发现 当一个接口被两个service实现时,controller调用接口实现功能,会报错,提示开发者指定service,官方是建议你使用@Qualifier来区分的,但是,总有另一种 ...