java中多个数字运算后值不对(失真)处理方法
最近遇到一个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中多个数字运算后值不对(失真)处理方法的更多相关文章
- js中多个数字运算后值不对(失真)处理方法
最近遇到一个bug ,在js里面计算两个数字相减,633011.20-31296.30 得到的结果居然是601714.89,领导不乐意了说怎么少了0.01,我一听,噶卵达,来达鬼,不可能啊,我Goog ...
- Java中url传递中文参数取值乱码的解决方法
java中URL参数中有中文值,传到服务端,在用request.getParameter()方法,得到的常常会是乱码,这将涉及到字符解码操作. 方法一: http://xxx.do?ptname=’我 ...
- js中Number数字数值运算后值不对
问题: 37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) 我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会这样,两 ...
- Java中的Bigdecimal类型运算
Java中的Bigdecimal类型运算 双精度浮点型变量double可以处理16位有效数.在实际应用中,需要对更大或者更小的数进行运算和处理.Java在java.math包中提 供的API类BigD ...
- java中int,float,long,double取值范围,内存泄露
java中int,float,long,double取值范围是多少? 写道 public class TestOutOfBound { public static void main(String[] ...
- Java 中 List 向前和向后遍历
Java 中 List 向前和向后遍历 import java.util.*; public class TestCollectionIterator { public static void mai ...
- 转:Java中子类是否可以继承父类的static变量和方法而呈现多态特性
原文地址:Java中子类是否可以继承父类的static变量和方法而呈现多态特性 静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明 ...
- java中多线程执行时,为何调用的是start()方法而不是run()方法
Thead类中start()方法和run()方法的区别 1,start()用来启动一个线程,当调用start()方法时,系统才会开启一个线程,通过Thead类中start()方法来启动的线程处于就绪状 ...
- 初识Java(Java数字处理类-大数字运算)
一.大数字运算 在 Java 中提供了大数字的操作类,即 java.math.BigInteger 类与 java.math.BigDecimal 类.这两个类用于高精度计算,体重 BigInteg ...
随机推荐
- 安装和测试Kafka(转)
http://blog.javachen.com/2015/03/17/install-and-test-kafka/# 本文主要介绍如何在单节点上安装 Kafka 并测试 broker.produc ...
- Influxdb数据压缩
环境: CentOS6.5_x64InfluxDB版本:1.1.0 数据压缩可以参考: https://docs.influxdata.com/influxdb/v1.1/concepts/stora ...
- oracle 如何查看oracle数据库版本
select * from v$version 写在最后 哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!! 相关推荐: 个人主页 oracle专题
- C#DES加密,JavaDES解密,另转C#和Java实现Des完整代码
C#DES加密,JavaDES解密,另转C#和Java实现Des完整代码 转载 2014年06月17日 17:36:09 标签: DES / C#DES / JavaDES / C#和Java交叉DE ...
- python之函数用法endswith()
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法endswith() #http://www.runoob.com/python/at ...
- Java微信分享接口开发
发布时间:2018-11-07 技术:springboot+maven 概述 微信JS-SDK实现自定义分享功能,分享给朋友,分享到朋友圈 详细 代码下载:http://www.demodas ...
- 点击threadItem查看MessageList时传递数据
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ...
- kubelet Pod status的状态分析
CrashLoopBackOff: 容器退出,kubelet正在将它重启 InvalidImageName: 无法解析镜像名称 ImageInspectError: 无法校验镜像 ErrImageNe ...
- 关于UDP-读这篇就够了(疑难杂症和使用)
本文为转载文章 原文链接:https://www.qcloud.com/community/article/848077001486437077 版权归原文所有 关于UDP 面向报文的传输方式决定了U ...
- 使用requests库实现多线程下载
多线程下载主要用到http请求中的header Content-Length:资源长度,用于确认资源的总长度,从而便于规划每个线程的任务量 Range:bytes=beg1-end1;beg2-end ...