位置:首页 » 文章/教程分享 » java除法保存小数点后位数的方法

在java中浮点型默认是double的,及2.00和1.10都要在计算机里转换进行二进制存储,这就涉及到数据精度,出现数值不对的现象的原因正是浮点型数据的精度问题。先了解下float、double的基本知识。

1. float和double是java的基本类型,用于浮点数表示,在java中float占4个字节32位,double占8个字节64位,一般比较适合用于工程测量计算中,其在内存里的存储结构如下:

float:


 符号位(1 bit)

指数(8 bit)

尾数(23 bit)

double:


符号位(1 bit)

指数(11 bit)

尾数(52 bit)


注意:从左到右是从低位到高位,而在计算机内部是采用逆序存储的。

2. System.out.println(2.00-1.10);中的1.10不能被计算机精确存储,以double类型数据1.10举例计算机如何将浮点型数据转换成二进制存储,
这里重点讲小数部分转换成二进制:
1.10整数部分就是1,转换成二进制1(这里整数转二进制不再赘述)
小数部分:0.1
0.1*2=0.2取整数部分0,基数=0.2
0.2*2=0.4取整数部分0,基数=0.4
0.4*2=0.8取整数部分0,基数=0.8
0.8*2=1.6取整数部分1,基数=1.6-1=0.6
0.6*2=1.2取整数部分1,基数=1.2-1=0.2
0.2*2=0.4取整数部分0,基数=0.4
.
.
.
.
直至基数为0。1.1用二进制表示为:1.000110...xxxx....(后面表示省略)
0.1 = 0*2^(-1)+0*2^(-2)+0*2^(-3)+1*2^(-4)+.........而double类型表示小数部分只有52位,当向后计算 52位后基数还不为0,那后面的部分只能舍弃,从这里可以看出float、double并不能准确表示每一位小数,对于有的小数只能无限趋向它。在计算机 中加减成除运算实际上最后都要在计算机中转换成二进制的加运算,由此,当计算机运行System.out.println(2.00-1.10);
时会拿他们在计算机内存中的二进制表示计算,而1.10的二进制表示本身就不准确,所以会出现0.8999999999999999的结果。

但为什么System.out.println(2.00f-1.10f);得出的结果是0.9呢。因为float精度没有double精度那么大,小数部分0.1二进制表示被舍去的比较多。

注意:

  • 程序中应尽量避免浮点数的比较
  • float、double类型的运算往往都不准确

解决方法:

使用BigDecimal提供的方法进行比较或运算,但要注意在构造BigDecimal的时候使用float、double的字符串形式构建,BigDecimal(String val);为什么不用BigDecimal(double val)API里写的比较清楚。

1.第1种办法
(double) (Math.round(sd3*10000)/10000.0);  // 这样为保持4位
(double) (Math.round(sd3*100)/100.0); // 这样为保持2位.

2.第2种办法

import java.text.DecimalFormat;
// 第一个为2位,第二个为3位.
DecimalFormat df2  = new DecimalFormat("###.00");
DecimalFormat df2  = new DecimalFormat("###.000");
System.out.println(df2.format(doube_var));

3.第3种办法

BigDecimal b1 = new BigDecimal(Double.toString(v1));  
BigDecimal b2 = new BigDecimal(Double.toString(v2));  
rslt = b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
// scale表示表示需要精确到小数点以后几位。

4.第4种办法

toBigInteger()   // 如果数字很大用这个,返回一个BigInteger类的对象(JAVA中有这样的类,如果你的程序确实只要整数的话就用这个类吧。),小数部分直接CUT。
intValue()  // 返回int型
longValue() // 返回long型

参考例子:

import java.math.BigDecimal;   
import java.text.DecimalFormat;   
  
public class TestGetInt {   
public static void main(String[] args) {   
double i = 2, j = 2.1, k = 2.5, m = 2.9;   
  
System.out.println("舍掉小数取整:Math.floor(" + i + ")=" + (int) Math.floor(i));   
System.out.println("舍掉小数取整:Math.floor(" + j + ")=" + (int) Math.floor(j));   
System.out.println("舍掉小数取整:Math.floor(" + k + ")=" + (int) Math.floor(k));   
System.out.println("舍掉小数取整:Math.floor(" + m + ")=" + (int) Math.floor(m));   
System.out.println();   
  
System.out.println("舍掉小数取整:Math.floor(-" + i + ")=" + (int) Math.floor(-i));   
System.out.println("舍掉小数取整:Math.floor(-" + j + ")=" + (int) Math.floor(-j));   
System.out.println("舍掉小数取整:Math.floor(-" + k + ")=" + (int) Math.floor(-k));   
System.out.println("舍掉小数取整:Math.floor(-" + m + ")=" + (int) Math.floor(-m));   
System.out.println();   
  
// 这段被注释的代码不能正确的实现四舍五入取整   
System.out.println("四舍五入取整:Math.rint(" + i + ")=" + (int) Math.rint(i));   
System.out.println("四舍五入取整:Math.rint(" + j + ")=" + (int) Math.rint(j));   
System.out.println("四舍五入取整:Math.rint(" + k + ")=" + (int) Math.rint(k));   
System.out.println("四舍五入取整:Math.rint(" + m + ")=" + (int) Math.rint(m));   
System.out.println();   
  
System.out.println("四舍五入取整:Math.rint(-" + i + ")=" + (int) Math.rint(-i));   
System.out.println("四舍五入取整:Math.rint(-" + j + ")=" + (int) Math.rint(-j));   
System.out.println("四舍五入取整:Math.rint(-" + k + ")=" + (int) Math.rint(-k));   
System.out.println("四舍五入取整:Math.rint(-" + m + ")=" + (int) Math.rint(-m));   
System.out.println();   
  
System.out.println("DecimalFormat四舍五入取整:(" + i + ")="   
+ new DecimalFormat("0").format(i));   
System.out.println("DecimalFormat四舍五入取整:(" + j + ")="   
+ new DecimalFormat("0").format(j));   
System.out.println("DecimalFormat四舍五入取整:(" + k + ")="   
+ new DecimalFormat("0").format(k));   
System.out.println("DecimalFormat四舍五入取整:(" + m + ")="   
+ new DecimalFormat("0").format(m));   
System.out.println();   
 
System.out.println("DecimalFormat四舍五入取整:(-" + i + ")="   
+ new DecimalFormat("0").format(-i));   
System.out.println("DecimalFormat四舍五入取整:(-" + j + ")="   
+ new DecimalFormat("0").format(-j));   
System.out.println("DecimalFormat四舍五入取整:(-" + k + ")="   
+ new DecimalFormat("0").format(-k));   
System.out.println("DecimalFormat四舍五入取整:(-" + m + ")="   
+ new DecimalFormat("0").format(-m));   
System.out.println();   
  
System.out.println("BigDecimal四舍五入取整:(" + i + ")="   
+ new BigDecimal("2").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println("BigDecimal四舍五入取整:(" + j + ")="   
+ new BigDecimal("2.1").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println("BigDecimal四舍五入取整:(" + k + ")="   
+ new BigDecimal("2.5").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println("BigDecimal四舍五入取整:(" + m + ")="   
+ new BigDecimal("2.9").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println();   
  
System.out.println("BigDecimal四舍五入取整:(-" + i + ")="   
+ new BigDecimal("-2").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println("BigDecimal四舍五入取整:(-" + j + ")="   
+ new BigDecimal("-2.1").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println("BigDecimal四舍五入取整:(-" + k + ")="   
+ new BigDecimal("-2.5").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println("BigDecimal四舍五入取整:(-" + m + ")="   
+ new BigDecimal("-2.9").setScale(0, BigDecimal.ROUND_HALF_UP));   
System.out.println();   
  
System.out.println("凑整:Math.ceil(" + i + ")=" + (int) Math.ceil(i));   
System.out.println("凑整:Math.ceil(" + j + ")=" + (int) Math.ceil(j));   
System.out.println("凑整:Math.ceil(" + k + ")=" + (int) Math.ceil(k));   
System.out.println("凑整:Math.ceil(" + m + ")=" + (int) Math.ceil(m));   
System.out.println();   
  
System.out.println("凑整:Math.ceil(-" + i + ")=" + (int) Math.ceil(-i));   
System.out.println("凑整:Math.ceil(-" + j + ")=" + (int) Math.ceil(-j));   
System.out.println("凑整:Math.ceil(-" + k + ")=" + (int) Math.ceil(-k));   
System.out.println("凑整:Math.ceil(-" + m + ")=" + (int) Math.ceil(-m));   
System.out.println();   
  
System.out.println("四舍五入取整:Math.round(" + i + ")=" + (int) Math.round(i));   
System.out.println("四舍五入取整:Math.round(" + j + ")=" + (int) Math.round(j));   
System.out.println("四舍五入取整:Math.round(" + k + ")=" + (int) Math.round(k));   
System.out.println("四舍五入取整:Math.round(" + m + ")=" + (int) Math.round(m));   
System.out.println();   
  
System.out.println("四舍五入取整:Math.round(-" + i + ")=" + (int) Math.round(-i));   
System.out.println("四舍五入取整:Math.round(-" + j + ")=" + (int) Math.round(-j));   
System.out.println("四舍五入取整:Math.round(-" + k + ")=" + (int) Math.round(-k));   
System.out.println("四舍五入取整:Math.round(-" + m + ")=" + (int) Math.round(-m));   
}   
测试输出结果如下:
舍掉小数取整:Math.floor(2.0)=2
舍掉小数取整:Math.floor(2.1)=2
舍掉小数取整:Math.floor(2.5)=2
舍掉小数取整:Math.floor(2.9)=2

舍掉小数取整:Math.floor(-2.0)=-2
舍掉小数取整:Math.floor(-2.1)=-3
舍掉小数取整:Math.floor(-2.5)=-3
舍掉小数取整:Math.floor(-2.9)=-3

四舍五入取整:Math.rint(2.0)=2
四舍五入取整:Math.rint(2.1)=2
四舍五入取整:Math.rint(2.5)=2
四舍五入取整:Math.rint(2.9)=3

四舍五入取整:Math.rint(-2.0)=-2
四舍五入取整:Math.rint(-2.1)=-2
四舍五入取整:Math.rint(-2.5)=-2
四舍五入取整:Math.rint(-2.9)=-3

DecimalFormat四舍五入取整:(2.0)=2
DecimalFormat四舍五入取整:(2.1)=2
DecimalFormat四舍五入取整:(2.5)=2
DecimalFormat四舍五入取整:(2.9)=3

DecimalFormat四舍五入取整:(-2.0)=-2
DecimalFormat四舍五入取整:(-2.1)=-2
DecimalFormat四舍五入取整:(-2.5)=-2
DecimalFormat四舍五入取整:(-2.9)=-3

BigDecimal四舍五入取整:(2.0)=2
BigDecimal四舍五入取整:(2.1)=2
BigDecimal四舍五入取整:(2.5)=3
BigDecimal四舍五入取整:(2.9)=3

BigDecimal四舍五入取整:(-2.0)=-2
BigDecimal四舍五入取整:(-2.1)=-2
BigDecimal四舍五入取整:(-2.5)=-3
BigDecimal四舍五入取整:(-2.9)=-3

凑整:Math.ceil(2.0)=2
凑整:Math.ceil(2.1)=3
凑整:Math.ceil(2.5)=3
凑整:Math.ceil(2.9)=3

凑整:Math.ceil(-2.0)=-2
凑整:Math.ceil(-2.1)=-2
凑整:Math.ceil(-2.5)=-2
凑整:Math.ceil(-2.9)=-2

四舍五入取整:Math.round(2.0)=2
四舍五入取整:Math.round(2.1)=2
四舍五入取整:Math.round(2.5)=3
四舍五入取整:Math.round(2.9)=3

四舍五入取整:Math.round(-2.0)=-2
四舍五入取整:Math.round(-2.1)=-2
四舍五入取整:Math.round(-2.5)=-2
四舍五入取整:Math.round(-2.9)=-3