您的位置:

java精度,java精度丢失问题

本文目录一览:

java 浮点数为什么精度会丢失

并不是java的浮点数精度会丢失,而是所有用二进制存储中的浮点数都可能会精度丢失(部分特殊的小数数值可以精确表示),所以计算机中存储的浮点数都存在精度丢失的风险,不过一边这个丢失的精度对我们正常的使用不会构成影响。

小数在转换为二进制时并不一定能用一个精确的二进制表示,大多数时候都是取的一个近似值,这就造成了精度的丢失。如果再用这个二进制进行计算,明显计算结果的精度会进一步丢失。

举个简单的例子把0.1用二进制表示(小数与二进制转换方法)

(1) 0.1 x 2 = 0.2  取整数位 0 得 0.0

(2) 0.2 x 2 = 0.4  取整数位 0 得 0.00

(3) 0.4 x 2 = 0.8  取整数位 0 得 0.000

(4) 0.8 x 2 = 1.6  取整数位 1 得 0.0001

(5) 0.6 x 2 = 0.2  取整数位 1 得 0.00011

(6) 0.2 x 2 = 0.4  取整数位 0 得 0.000110

(7) 0.4 x 2 = 0.8  取整数位 0 得 0.0001100

(8) 0.8 x 2 = 1.6  取整数位 1 得 0.00011001

(9) 0.6 x 2 = 1.2  取整数位 1 得 0.000110011

(n) ...

得到一个无限循环的二进制小数 0.000110011…,没办法用一个精确的二进制表示0.1。而且计算机中存储一个浮点数所用的位数也是有限的,所以只能选择在某一个精度进行保存。

当然也有特殊的小数,比如0.25的二进制为0.01

附:代码之谜(五)- 浮点数(谁偷了你的精度?)

关于java单精度与双精度的问题

单精度和双精度的区别就是,双精度要比单精度所存储的位数要多,至于说3.14师双精度,是因为Java中,默认的小数都是double类型,也就算双精度的,如果要定义单精度的话,那就要在小数的后面加上一个f或者F,即 double d = 3.14; float f = 3.14f; 一定要注意后面有没有“f”和“F”啊,这个初学的时候,经常会考到。楼上说的,是对,但是,他那样写,就一定会报错。记住,单精度的变量定义,一定要在值的后面加上标识。

Java语言中的浮点型数据的float和double的单精度和双精度到底是啥意思?

主要有下面几个区别,手册上的,希望能帮到你

1、变量类型不同

float属于单精度型浮点数据。

double属于双精度型浮点数据。

2、指数范围不同

float的指数范围为-127~128。

double而double的指数范围为-1023~1024

3、表达式指数位不同

float的表达式为1bit(符号位)+8bits(指数位)+23bits(尾数位)

double的表达式为1bit(符号位)+ 11bits(指数位)+ 52bits(尾数位)

4、占用内存空间不同

float占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38。

double占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308。

5、有效位数不同

float只能提供七位有效数字。

double可提供16位有效数字。

怎么控制精度在java

JAVA中如何对double或者float的浮点数进行精度计算,在JAVA中提供了多种参数来实现精度的不同控制方式。具体例子如下: 

转自

Java代码 

/* 

 * Created on 2005-6-5 

 * Author stephen 

 * Email zhoujianqiang AT gmail DOT com 

 * CopyRight(C)2005-2008 , All rights reserved. 

 */  

package com.soft4j.utility;  

  

import java.math.BigDecimal;  

  

/** 

 * 与小数位精度(四舍五入等)相关的一些常用工具方法. 

 *  

 * float/double的精度取值方式分为以下几种: br 

 * java.math.BigDecimal.ROUND_UP br 

 * java.math.BigDecimal.ROUND_DOWN br 

 * java.math.BigDecimal.ROUND_CEILING br 

 * java.math.BigDecimal.ROUND_FLOOR br 

 * java.math.BigDecimal.ROUND_HALF_UPbr 

 * java.math.BigDecimal.ROUND_HALF_DOWN br 

 * java.math.BigDecimal.ROUND_HALF_EVEN br 

 *  

 * @author stephen 

 * @version 1.0.0 

 */  

public final class RoundTool {  

  

    /** 

     * 对double数据进行取精度. 

     * p 

     * For example: br 

     * double value = 100.345678; br 

     * double ret = round(value,4,BigDecimal.ROUND_HALF_UP); br 

     * ret为100.3457 br 

     *  

     * @param value 

     *            double数据. 

     * @param scale 

     *            精度位数(保留的小数位数). 

     * @param roundingMode 

     *            精度取值方式. 

     * @return 精度计算后的数据. 

     */  

    public static double round(double value, int scale, int roundingMode) {  

        BigDecimal bd = new BigDecimal(value);  

        bd = bd.setScale(scale, roundingMode);  

        double d = bd.doubleValue();  

        bd = null;  

        return d;  

    }  

  

    /** 

     * 测试用的main方法. 

     *  

     * @param argc 

     *            运行参数. 

     */  

    public static void main(String[] argc) {  

        //下面都以保留2位小数为例  

          

        //ROUND_UP  

        //只要第2位后面存在大于0的小数,则第2位就+1  

        System.out.println(round(12.3401,2,BigDecimal.ROUND_UP));//12.35  

        System.out.println(round(-12.3401,2,BigDecimal.ROUND_UP));//-12.35  

        //ROUND_DOWN  

        //与ROUND_UP相反  

        //直接舍弃第2位后面的所有小数  

        System.out.println(round(12.349,2,BigDecimal.ROUND_DOWN));//12.34  

        System.out.println(round(-12.349,2,BigDecimal.ROUND_DOWN));//-12.34  

        //ROUND_CEILING  

        //如果数字0 则和ROUND_UP作用一样  

        //如果数字0 则和ROUND_DOWN作用一样  

        System.out.println(round(12.3401,2,BigDecimal.ROUND_CEILING));//12.35  

        System.out.println(round(-12.349,2,BigDecimal.ROUND_CEILING));//-12.34  

        //ROUND_FLOOR  

        //如果数字0 则和ROUND_DOWN作用一样  

        //如果数字0 则和ROUND_UP作用一样  

        System.out.println(round(12.349,2,BigDecimal.ROUND_FLOOR));//12.34  

        System.out.println(round(-12.3401,2,BigDecimal.ROUND_FLOOR));//-12.35  

        //ROUND_HALF_UP [这种方法最常用]  

        //如果第3位数字=5,则第2位数字+1  

        //备注:只看第3位数字的值,不会考虑第3位之后的小数的  

        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_UP));//12.35  

        System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_UP));//12.34  

        System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_UP));//-12.35  

        System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_UP));//-12.34  

        //ROUND_HALF_DOWN  

        //如果第3位数字=5,则做ROUND_UP  

        //如果第3位数字5,则做ROUND_DOWN  

        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_DOWN));//12.35  

        System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_DOWN));//12.34  

        System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_DOWN));//-12.35  

        System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_DOWN));//-12.34  

        //ROUND_HALF_EVEN  

        //如果第3位是偶数,则做ROUND_HALF_DOWN  

        //如果第3位是奇数,则做ROUND_HALF_UP  

        System.out.println(round(12.346,2,BigDecimal.ROUND_HALF_EVEN));//12.35  

        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_EVEN));//12.35  

    }  

}

 如果要求精确控制位数,推荐使用BigDecimal,这是在JDK1.4版本之后推荐的一个处理精度的类。