最近遇到一个bug ,在java里面计算两个数字相减,633011.20-31296.30

得到的结果居然是601714.8999999999,丢失精度了,原来这是Java浮点运算的一个bug。

解决方法:网上找到了一些解决办法,就是重新写了一些浮点运算的函数。
下面就把这些方法摘录下来,以供遇到同样问题的朋友参考:

简易计算器点击下载

js中多个数字运算后值不对(失真)处理方法

调用方法:

public static void main(String[] args) throws Exception{
System.out.println("加法未处理:0.05+0.01="+(0.05+0.01));
System.out.println("加法已处理:0.05+0.01="+add(0.05,0.01));
System.out.println("减法未处理:1.0-0.42="+(1.0-0.42));
System.out.println("减法已处理:1.0-0.42="+sub(1.0,0.42));
System.out.println("减法未处理:633011.20-31296.30="+(633011.20-31296.30));
System.out.println("减法已处理:633011.20-31296.30="+sub(633011.20,31296.30));
System.out.println("乘法未处理:4.015*10="+(4.015*100));
System.out.println("乘法已处理:4.015*10="+mul(4.015,100));
System.out.println("除法未处理:123.3/100="+(123.3/100));
System.out.println("除法已处理:123.3/100="+division(123.3,100));
}

控制台输出效果:

加法未处理:0.05+0.01=0.060000000000000005
加法已处理:0.05+0.01=0.06
减法未处理:1.0-0.42=0.5800000000000001
减法已处理:1.0-0.42=0.58
减法未处理:633011.20-31296.30=601714.8999999999
减法已处理:633011.20-31296.30=601714.9
乘法未处理:4.015*10=401.49999999999994
乘法已处理:4.015*10=401.5
除法未处理:123.3/100=1.2329999999999999
除法已处理:123.3/100=1.23

java程序代码

1.加法运算

    /**
* 计算两个值的加法运算
* @param arg1
* @param arg2
* @return
* @throws Exception
*/
public static double add(double arg1,double arg2) throws Exception{
String arg11 = arg1+"";
String arg22 = arg2+"";
int r1 = 0;
int r2 = 0;
int m = 0;
try{
r1=arg11.split("\\.")[1].length();
}catch(Exception e){
r1=0;
}
try{
r2=arg22.split("\\.")[1].length();
}catch(Exception e){
r2=0;
}
m=(int) Math.pow(10,Math.max(r1,r2)); return (arg1 * m + arg2 * m)/m;
}

2.减法运算

    /**
* 计算两个值的减法运算
* @param arg1
* @param arg2
* @return
* @throws Exception
*/
public static double sub(double arg1,double arg2) throws Exception{
String arg11 = arg1+"";
String arg22 = arg2+"";
int r1 = 0;
int r2 = 0;
int m = 0;
int n = 0;
try{
r1=arg11.split("\\.")[1].length();
}catch(Exception e){
r1=0;
}
try{
r2=arg22.split("\\.")[1].length();
}catch(Exception e){
r2=0;
} m = (int)Math.pow(10, Math.max(r1, r2));
//last modify by deeka
//动态控制精度长度
n = (r1 >= r2) ? r1 : r2;
double result = ((arg1 * m - arg2 * m) / m); //BigDecimal.ROUND_HALF_UP表示四舍五入,BigDecimal.ROUND_HALF_DOWN也是五舍六入,BigDecimal.ROUND_UP表示进位处理(就是直接加1),BigDecimal.ROUND_DOWN表示直接去掉尾数。
BigDecimal b = new BigDecimal(result);
result = b.setScale(n, BigDecimal.ROUND_HALF_UP).doubleValue();
return result;
}

3.乘法运算

    /**
* 计算两个值的乘法运算
* @param arg1
* @param arg2
* @return
* @throws Exception
*/
public static double mul(double arg1,double arg2) throws Exception{
String arg11 = arg1+"";
String arg22 = arg2+"";
int m = 0;
try{
m+=arg11.split("\\.")[1].length();
}catch(Exception e){
System.out.println("计算出错");
}
try{
m+=arg22.split("\\.")[1].length();
}catch(Exception e){
System.out.println("计算出错");
}
return Integer.parseInt(arg11.replace(".",""))*Integer.parseInt(arg22.replace(".",""))/Math.pow(10,m);
}

4.除法运算

    /**
* 计算两个值的除法运算
* @param arg1
* @param arg2
* @return
* @throws Exception
*/
public static double division(double arg1,double arg2) throws Exception{
String arg11 = arg1+"";
String arg22 = arg2+"";
int t1 = 0;
int t2 = 0;
int r1 = 0;
int r2 = 0;
try{
t1=arg11.split("\\.")[1].length();
}catch(Exception e){
System.out.println("计算出错");
}
try{
t2=arg22.split("\\.")[1].length();
}catch(Exception e){
System.out.println("计算出错");
}
r1=Integer.parseInt(arg11.replace(".",""));
r2=Integer.parseInt(arg22.replace(".",""));
double result = ((float)r1/r2)*(Math.pow(10,t2-t1));
//BigDecimal.ROUND_HALF_UP表示四舍五入,BigDecimal.ROUND_HALF_DOWN也是五舍六入,BigDecimal.ROUND_UP表示进位处理(就是直接加1),BigDecimal.ROUND_DOWN表示直接去掉尾数。
BigDecimal b = new BigDecimal(result);
result = b.setScale(t1 + t2, BigDecimal.ROUND_HALF_UP).doubleValue();
return result;
}

java中多个数字运算后值不对(失真)处理方法的更多相关文章

  1. js中多个数字运算后值不对(失真)处理方法

    最近遇到一个bug ,在js里面计算两个数字相减,633011.20-31296.30 得到的结果居然是601714.89,领导不乐意了说怎么少了0.01,我一听,噶卵达,来达鬼,不可能啊,我Goog ...

  2. Java中url传递中文参数取值乱码的解决方法

    java中URL参数中有中文值,传到服务端,在用request.getParameter()方法,得到的常常会是乱码,这将涉及到字符解码操作. 方法一: http://xxx.do?ptname=’我 ...

  3. js中Number数字数值运算后值不对

    问题: 37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) 我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会这样,两 ...

  4. Java中的Bigdecimal类型运算

    Java中的Bigdecimal类型运算 双精度浮点型变量double可以处理16位有效数.在实际应用中,需要对更大或者更小的数进行运算和处理.Java在java.math包中提 供的API类BigD ...

  5. java中int,float,long,double取值范围,内存泄露

    java中int,float,long,double取值范围是多少? 写道 public class TestOutOfBound { public static void main(String[] ...

  6. Java 中 List 向前和向后遍历

    Java 中 List 向前和向后遍历 import java.util.*; public class TestCollectionIterator { public static void mai ...

  7. 转:Java中子类是否可以继承父类的static变量和方法而呈现多态特性

    原文地址:Java中子类是否可以继承父类的static变量和方法而呈现多态特性 静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明 ...

  8. java中多线程执行时,为何调用的是start()方法而不是run()方法

    Thead类中start()方法和run()方法的区别 1,start()用来启动一个线程,当调用start()方法时,系统才会开启一个线程,通过Thead类中start()方法来启动的线程处于就绪状 ...

  9. 初识Java(Java数字处理类-大数字运算)

    一.大数字运算 在 Java 中提供了大数字的操作类,即 java.math.BigInteger 类与  java.math.BigDecimal 类.这两个类用于高精度计算,体重 BigInteg ...

随机推荐

  1. 算法笔记_203:第四届蓝桥杯软件类决赛真题(C语言B组)

    目录 1 猜灯谜 2 连续奇数和 3 空白格式化 4 高僧斗法 5 格子刷油漆 6 农场阳光   前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 猜灯谜 标题:猜灯谜 A 村的元宵节灯会上有一迷题: ...

  2. Linux alias别名设置

    alias命令用来设置指令的别名.我们可以使用该命令可以将一些较长的命令进行简化.使用alias时,用户必须使用单引号''将原来的命令引起来,防止特殊字符导致错误. 语法 alias(选项)(参数) ...

  3. Window10激活

    Windows10激活,通过kms激活. 01.安装对应版本的秘钥 专业版:W269N-WFGWX-YVC9B-4J6C9-T83GX 企业版:NPPR9-FWDCX-D2C8J-H872K-2YT4 ...

  4. Web-URL编码流程图(详细了解乱码原因)

    URL编码流程图 原URL---->GET时浏览器根据HTTP头的Content-Type的charset,POST根据(<meta http-equiv="Content-Ty ...

  5. 禁止logback输出状态信息

    一.问题描述 22:18:07,299 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resourc ...

  6. spring加载jar包中多个配置文件(转)

    转自:http://evan0625.iteye.com/blog/1598366 在使用spring加载jar包中的配置文件时,不支持通配符,需要一个一个引入,如下所示: Java代码 <co ...

  7. 树莓派进阶之路 (019) - 树莓派通过filezilla,samba与PC文件共享(转)

    虽然我们可以很方便的通过ssh譬如putty或者vnc连接操控树莓派,但是毕竟树莓派资源没那么高,在上面编程,调试要吃力的多.所以还是想在pc上编程上传到树莓派或者最好,文件共享,可以直接读写共同的文 ...

  8. 树莓派进阶之路 (012) - 树莓派配置文档 config.txt 说明

    原文连接:http://elinux.org/RPi_config.txt 由于树莓派并没有传统意义上的BIOS, 所以现在各种系统配置参数通常被存在”config.txt”这个文本文件中. 树莓派的 ...

  9. Nginx反向代理+Tomcat+Springmvc获取用户访问ip

    Nginx+Tomcat+Springmvc获取用户访问ip 1.Nginx反向代理 修改Nginx配置文件 location / { ***********之前代码*******; proxy_se ...

  10. 安卓高手之路之ClassLoader(二)

    因为ClassLoader一定与虚拟机的启动有关系,那么必须从Zygote的启动开始看代码.下面就分析一下这些代码,行数不多: int main(int argc, const char* const ...