本文目录一览:
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版本之后推荐的一个处理精度的类。