java丢失精度问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java丢失精度问题相关的知识,希望对你有一定的参考价值。

float a = 3.14f

为什么3.14会超出表值范围
为什么加 “ f ” 转成比double误差大的float反而不会丢失精度

float a = 3.14;这个语句的意思是把双精度浮点类型(double)赋值给单精度浮点类型(float)的变量a,把一个高精度的数赋值给一个低精度的数,就会照成精度丢失了。因为Java中,3.14这样的写法默认是认为double类型的,而3.14f这样的写法就会指定3.14这个数为float类型,这样赋值就不会有精度丢失了。注意,这里你不要单纯的把float想像成只能存一位小数点的数,3.14这个数同样用float可以存下 参考技术A 并不是会丢失精度,而是3.14默认是double类型,不能自动转型为float追问

那么加f是强制转型吗

追答

参考技术B 解决方案
使用BigDecimal并且一定要用String来够造。
做一个加法运算,需要先将两个浮点数转为String,然后够造成BigDecimal,在其中一个上调用add方法,传入另
一个作为参数,然后把运算的结果(BigDecimal)再转换为浮点数。你能够忍受这么烦琐的过程吗?下面我们提供一个工具类Arith来简化操作。它
提供以下静态方法,包括加减乘除和四舍五入:
public static double add(double v1,double v2)
public static double sub(double v1,double v2)
public static double mul(double v1,double v2)
public static double div(double v1,double v2)
public static double div(double v1,double v2,int scale)
public static double round(double v,int scale)

一般对double类型进行运算时,做好对结果进行处理,然后拿这个值去做其他事情。
使用如下:

/**
* 对double数据进行取精度.
* @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;


/**
* double 相加
* @param d1
* @param d2
* @return
*/
public double sum(double d1,double d2)
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.add(bd2).doubleValue();


/**
* double 相减
* @param d1
* @param d2
* @return
*/
public double sub(double d1,double d2)
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.subtract(bd2).doubleValue();


/**
* double 乘法
* @param d1
* @param d2
* @return
*/
public double mul(double d1,double d2)
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.multiply(bd2).doubleValue();


/**
* double 除法
* @param d1
* @param d2
* @param scale 四舍五入 小数点位数
* @return
*/
public double div(double d1,double d2,int scale)
// 当然在此之前,你要判断分母是否为0,
// 为0你可以根据实际需求做相应的处理

BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.divide
(bd2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();


这样,计算double类型的数据计算问题就可以处理了。
另外补充一下 javascript 四舍五入的方法:
小数点问题
Math.round(totalAmount*100)/100 (保留 2 位)

function formatFloat(src, pos)

return Math.round(src*Math.pow(10, pos))/Math.pow(10, pos);
参考技术C 使用
BigDecimal

以上是关于java丢失精度问题的主要内容,如果未能解决你的问题,请参考以下文章

前端获取Long类型精度丢失解决办法

Java double和 float丢失精度问题

Java 中的 BigDecimal 运算,如何解决精度丢失问题?

Java Long类型处理精度丢失问题

Java Long类型处理精度丢失问题

Java Long类型处理精度丢失问题