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 ...
随机推荐
- Akka边学边写(4)-- MiniRPG
前面几篇文章用Akka写了HelloWorld和EchoServer,为了更进一步学习Akka,本文将会实现一个非常小的RPG游戏server:MiniRPG. 游戏逻辑 由于是迷你RPG,所以逻辑非 ...
- Android RingtoneManager 铃声管理
package com.Aina.Android; import java.io.File; import android.app.Activity; import android.content.I ...
- js常用数据转换&判断
数组转字符串 var a, b; a = new Array(0,1,2,3,4); b = a.join("-"); //"0-1-2-3-4" 字符串转数组 ...
- [React] Remove React PropTypes by using Flow Annotations (in CRA)
Starting from v15.5 if we wanted to use React's PropTypes we had to change our code to use a separat ...
- 基于am3358的led跑马灯測试
#include <sys/ioctl.h> #include<stdio.h> #include <fcntl.h> #include <sys/types ...
- 格式化时间的一个好方法(补充moment)
/** * * 格式化时间 * @param {*} time * @param {*} fmt * @returns * time(new Date(), 'yyyy/MM/dd') ==> ...
- CSS笔记 - fgm练习 - 三个div变色 - CSS div等分布局
<title>三个div变红</title> <style> *{margin: 0; padding: 0} body{ text-align: center; ...
- SQL Server2008 Hierarchyid数据类型
以往我们在关系数据库中建立树状结构的时候,通常使用ID+ParentID来实现两条 纪录间的父子关系.但这种方式只能标示其相对位置.解决这类问题在SqlServer2005出现之前通常是采用游标来操作 ...
- ping 本地端口
C:\Users\Administrator>netstat -ano | findstr 8001
- storm集群操作指南
目录 storm集群操作指南 一.storm伪分布式安装 (一)环境准备 (二)安装zookeeper (三)安装storm (四)运行程序 二.storm集群安装 (一)下载storm并解压 (二) ...