Java中的浮点数-科学计数法-加减乘除
上次,提到“元转分”这个浮点数问题,boss倾向于手动把1.23元这种格式,转换成123分。
但实际上,浮点数很容易遇到精度问题。
比如,System.out.println(4.015 * 1000);结果就不会是4015。
以前,总结的元转分的问题,没能考虑到所有的场景,今天补充点上次遗漏的。
-5.09,如果金额是负数,应该是-500-9=-509,而不是-500+9=-441,这是上次的一个超级bug。
另外,需要还有一个超级bug,“1045189788”转换成double类型的元时,结果变成了1.04。
debug了好久,才发现以前代码的漏洞。
1045189788这种比较大的浮点数,在传递过程中,是“科学计数法”表示的,类似“1.04E”,
所以,最后转换出了问题。
其实,我一直不建议boss采用这种人工截取计算的方式,需要考虑的场景太复杂,建议使用JDK内置的BigDecimal。
经过实践,发现很不错。
可以用double、string等多种原始类型,构造BigDecimal,再进行四则运算。
使用BigDecimal的关键是,控制“标度”即“精度”,scale。
算术运算结果的首选标度 运算 结果的首选标度
加 max(addend.scale(), augend.scale())
减 max(minuend.scale(), subtrahend.scale())
乘 multiplier.scale() + multiplicand.scale()
除 dividend.scale() - divisor.scale()
下面这个工具类,是从网上copy的,还是非常有价值的。
import java.math.BigDecimal;
/**
* 消除加减乘除的精度,解决Float与Double类型进度不准确的问题.
*/
public class DoubleUtil {
/**
* 加法运算
*
* @param v1
* @param v2
* @return
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 减法运算
*
* @param v1
* @param v2
* @return
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 乘法运算
*
* @param v1
* @param v2
* @return
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 除法运算
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 商
*/
public static double div(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2).doubleValue();
}
/**
* 除法运算
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 商和余数
*/
public static BigDecimal[] divideAndRemainder(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
BigDecimal[] arr = b1.divideAndRemainder(b2);
return arr;
}
/**
* 求商(向下舍入)
*
* @param v1
* @param v2
* @return
*/
public static BigDecimal divideToIntegralValue(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
System.out.println("------------");
return b1.divideToIntegralValue(b2);
}
public static void main(String[] args) {
testUnPrecision();
System.out.println("----------使用BigDecimal消除精度影响------------\n"
+ DoubleUtil.add(0.05, 0.01));
System.out.println(DoubleUtil.sub(1.0, 0.54));
System.out.println(DoubleUtil.mul(4.015, 1000));
System.out.println(DoubleUtil.div(12.3, 10));
// 得到商和余数
BigDecimal[] arr = DoubleUtil.divideAndRemainder(12.3, 10);
System.out.println("得到商和余数");
for (BigDecimal bigDecimal : arr) {
System.out.println(bigDecimal);
}
System.out.println(DoubleUtil.divideToIntegralValue(4.5, 2));
}
/**
* 不准确问题示例
*/
private static void testUnPrecision() {
System.out.println("--------Java自身的Double类型有精度损失----------");
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.54);
System.out.println(4.015 * 1000);
System.out.println(12.3 / 100);
}
}
Java中的浮点数-科学计数法-加减乘除的更多相关文章
- Java中怎么把科学计数法显示出全部数字
如果想去除科学计数法显示可以用如下方法处理: /** * 把科学计数法显示出全部数字 * @param d */ public static String object2Str(Object d) { ...
- 把Excel作为数据库,读到DataTable中,Excel科学计数法数字转字符串
需要引用:using System.Data.OleDb; /// <summary> /// 获取Excel数据,包含所有sheet /// </summary> /// & ...
- 将Excel中读取的科学计数法表示的Double数据转换为对应的字符串
已在SegmentFault提问,目前没有答案,自行实现如下: private static String getRealNumOfScientificNotation(String doubleSt ...
- Java 科学计数法
目录 Java 科学计数法 1 科学计数法的概念 1.1 有效数字 1.2 E记号 2 Java中的科学计数法 2.1 NumberFormat 2.2 DecimalFormat 2.3 BigDe ...
- 数据库字段出现科学计数法e+的情况分析
问题: 有时候,我们在将excel表格中数据导入数据库中时,对于表格中的数字会默认为float的数据类型,这个时候导入到数据库中的这个表的值是正常显示的: 然而如果你要把导入到数据库中的表,再插入到另 ...
- 解决从Excel导入数据库,导入到DataTable时数据类型发生变化的问题(如数字类型变成科学计数法,百分数变成小数)
做项目的时候,C#读取Excel数据到DataTable或者DataSet,设断点查看DataTable,发现Excel的显示为较长位数数字的字段如0.000012在DataTable中显示为科学计数 ...
- 如何使java中double类型不以科学计数法表示
在java中,把一个double或者BigDecimal的小数转换为字符串时,经常会用科学计数法表示,而我们一般不想使用科学计数法,可以通过:DecimalFormat a = new Decimal ...
- Java将Excel中科学计数法解析成数字
需要注意的是一般的科学表达式是1.8E12 1.8E-12 而在Excel中的科学表达式是1.8E+12 1.8E-12 我写的科学计数法的正则表达式是(-?\d+\.?\d*)[Ee]{1}[\+- ...
- java使用poi解析或处理excel的时候,如何防止数字变成科学计数法的形式和其他常见Excel中数据转换问题
当使用POI处理excel的时候,遇到了比较长的数字,虽然excel里面设置该单元格是文本类型的,但是POI的cell的类型就会变成数字类型. 而且无论数字是否小数,使用cell.getNumberi ...
随机推荐
- Hi35xx NVR GDB调试
Hi35xx NVR GDB调试 1. 下载gdb源代码 嵌入式Linux 的GDB 调试环境由Host 和Target 两部分组成,Host 端使用arm-linuxgdb,Target Boa ...
- eclipse- log 打印跟输出到文件
1.在eclipse中打印log,经常使用的就是log.e(string,string) 代码中如下 @Override public boolean onTouchEvent(MotionEvent ...
- dot 语法全介绍
0. 保存 保存为 pdf:dot -Tpdf iris.dot -o iris.pdf 1. 基本 (1)无向图.有向图.子图 graph G {} // 无向图 digraph G {} // 有 ...
- UART和RS232/RS485的关系,RS232与RS485编程
http://wpp9977777.blog.163.com/blog/static/4625100720138495943540/ 串口通讯是电子工程师和嵌入式开发工程师面对的最基本问题,RS232 ...
- .v 和 .sdf
DC输出的.v(网表?)和.sdf(储存的是延时的信息) 用于后仿真
- Java Web学习总结(3)——Servlet详解
一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些 ...
- 开发过程使用Tomcat Maven插件持续快捷部署Web项目
我在平时工作中部署Web项目到测试服务器上的Tomcat时用的是Hudson.Hudson本身已经跟SVN.Git.Maven集成并且支持添加各种插件.但如果使用Hudson,我需要配置两个任务:一个 ...
- [Spark源代码剖析] DAGScheduler划分stage
转载请标明出处:http://blog.csdn.net/bigbigdata/article/details/47293263 本文基于Spark 1.3.1 先上一些stage相关的知识点: DA ...
- shell基础之符号与语法
shell脚本如今已经成为了一种非常普遍的脚本语言,之所以如此广泛的被应用,毋庸置疑它是有它的独到之处的.shell脚本语言和其它的语言比方说c/c++有何不同呢?c/c++等语言属于 ...
- 深入理解线程本地变量ThreadLocal
ThreadLocal理解: 假设在多线程并发环境中.一个可变对象涉及到共享与竞争,那么该可变对象就一定会涉及到线程间同步操作,这是多线程并发问题. 否则该可变对象将作为线程私有对象,可通过Threa ...