android int 首位值_Android中数值的精确计算
Android中数值计算的精度
在平常的开发中,会经常进行数值的计算,而如何才能更加准确的得到计算结果是最重要的,最近在做一个金融类的项目,其中涉及到黄金的计算,所以写这篇文章来总结一下,如何对数值的计算更加精确完美,这是本人在简书的第一篇文章,欢迎大家留言讨论。
问题起源:
作为一名利用Java的开发人员,当遇到数值计算的时候首先想到的自然就是Double和Float,Double的精度值是16位,Float的精度值为8位,对于精度要求不是足够高的话完全是够用了。本人开始就是采用Double类型的对黄金的克重以及总额来进行计算的,但是在测试中发现了问题,数值小的时候还正确,但是当数值越大差值也就明显了。
for example:
double a = 11540.0;
double b = 0.855;
Double double1 = a* b;
System.out.println("double=="+double1);
打印结果:double==9866.699999999999
其实这两个数字的乘积是整数:9866.7,其实在Java中为什么会总是出现double值的乘积总是在一个正确的结果左右偏0.0000**1,这是因为当两个double数值相乘时,底层采用转换成二进制来进行乘法的运算,由于在乘完之后在包含小数的二进制中无法完全转换成十进制才会发生这种情况。
解决办法
Java中有一个类是BigDecimal,该类是专门计算一些要求精度很高的算法,常用于银行金融类的计算,BigDecimal一共有4个够造方法,我们不关心用BigInteger来够造的那两个,那么还有两个, 它们是:
BigDecimal(double val)
Translates a double into a BigDecimal.
BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.
但是在测试中直接将Double值传进去,也就是调用第一个构造方法来创建的BigDecimal也会损失精度,具体这里先不说了,(完了再看一下源码),因此本人只是利用第二个构造函数来进行对BigDecimal来创建对象的,下面是我写的一个工具类:
/**
*
* 作者: 卢卫成 时间: 2017年9月2日 功能描述: 用于对数值的精确计算工具类
*
*/
public class CalcUtils {
public static final int TYPE_ADD = 0x00; // 加法
public static final int TYPE_MULTIPLY = 0x01; // 乘法
public static final int TYPE_DIVIDE = 0x02; // 除法
public static final int TYPE_SUBTRACT = 0x03; // 减法
/**
* 加法
* @param a
* @param b
* @return
*/
public static Double add(Double a, Double b) {
return calc(a, b, -1, TYPE_ADD, null);
}
/**
* 减法
* @param a
* @param b
* @return
*/
public static Double sub(Double a, Double b) {
return calc(a, b, -1, TYPE_SUBTRACT, null);
}
/**
* 乘法
* @param a
* @param b
* @return
*/
public static Double multiply(Double a, Double b) {
return calc(a, b, -1, TYPE_MULTIPLY, null);
}
/**
* 除法
* @param a
* @param b
* @return
*/
public static Double divide(Double a, Double b) {
return calc(a, b, -1, TYPE_DIVIDE, null);
}
/**
* 乘法
* @param a
* @param b
* @param scale 小数点后保留的位数
* @param mode 保留的模式
* @return
*/
public static Double multiply(Double a, Double b, int scale, RoundingMode mode) {
return calc(a, b, scale, TYPE_MULTIPLY, mode);
}
/**
* 除法
* @param a
* @param b
* @param scale 小数点后保留的位数
* @param mode 保留的模式
* @return
*/
public static Double divide(Double a, Double b, int scale, RoundingMode mode) {
return calc(a, b, scale, TYPE_DIVIDE, mode);
}
/**
* 计算
* @param a
* @param b
* @param scale
* @param type
* @param mode
* @return
*/
private static Double calc(Double a, Double b, int scale, int type, RoundingMode mode) {
BigDecimal result = null;
BigDecimal bgA = new BigDecimal(String.valueOf(a));
BigDecimal bgB = new BigDecimal(String.valueOf(b));
switch (type) {
case TYPE_ADD:
result = bgA.add(bgB);
break;
case TYPE_MULTIPLY:
result = bgA.multiply(bgB);
break;
case TYPE_DIVIDE:
try {
result = bgA.divide(bgB);
} catch (ArithmeticException e) {// 防止无限循环而报错 采用四舍五入保留3位有效数字
result = bgA.divide(bgB,3,RoundingMode.HALF_DOWN);
}
break;
case TYPE_SUBTRACT:
result = bgA.subtract(bgB);
break;
}
if (mode==null) {
if(scale!=-1){
result = result.setScale(scale);
}
}else{
if(scale!=-1){
result = result.setScale(scale,mode);
}
}
return result.doubleValue();
}
}
这里涉及到两个参数:Scale和RoundingMode
Scale
scale是用来对利用BigDecimal对数值进行运算后保留的位数。
RouningMode
该参数是BigDecimal是一个枚举类,包含有8个枚举类型,用来说明对经过计算后数值的取舍模式:
ROUND_UP:远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。
ROUND_DOWN:趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。
ROUND_CEILING:向正无穷方向舍入。向正最大方向靠拢。若是正数,舍入行为类似于ROUND_UP,若为负数,舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。
ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。
HALF_UP:最近数字舍入(5进)。这是我们最经典的四舍五入。
HALF_DOWN:最近数字舍入(5舍)。在这里5是要舍弃的。
HAIL_EVEN:银行家舍入法。
android int 首位值_Android中数值的精确计算相关推荐
- android int 首位值_Android应用视图的管理者Window
点击上方蓝色文字关注我哦 Window在Android是一个窗口的概念,日常开发中我们和它接触的不多,我们更多接触的是View,但是View都是通过Window来呈现的,Window是View的直接管 ...
- android 自定义banner样式_Android中Banner的指示器自定义View
Banner是我们经常会遇到的一个功能,有很多是需要支持滑动是有个当前的指示器界面,一般如果为了图省事的方案可以用LinearLayout然后不断的在里面添加View,把背景通过shape来设置圆形. ...
- android打开视频噔_Android中三种视频的播放
在Android中,我们有三种方式来实现视频的播放: 1.使用其自带的播放器.指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型. 2.使用VideoView来播放. ...
- android 调用java类_Android中在WebView里实现Javascript调用Java类的方法
搜索热词 为了方便网页和Android应用的交互,Android系统提供了WebView中JavaScript网页脚本调用Java类方法的机制.只要调用addJavascriptInterface方法 ...
- android 弹窗有边框_android中常用的弹出提示框
我们在平时做开发的时候,免不了会用到各种各样的对话框,相信有过其他平台开发经验的朋友都会知道,大部分的平台都只提供了几个最简单的实现,如果我们想实现自己特定需求的对话框,大家可能首先会想到,通过继承等 ...
- android判断主线程_android中从子线程切换到主线程,但是显得代码很臃肿,请教大牛是怎么自定义的?...
小弟新手一枚,我先来说说我自己在项目中的做法.因为小弟只有JAVAWEB的基础所以只能使用线程池来处理线程之间的切换 1.为了使APP不出现卡顿和内存的低消耗.我是用了synchronized 和用一 ...
- android反射开启通知_Android中反射的简单应用
自己对反射的理解和应用还处于比较浅显的阶段,写这篇文章更多在于整理总结,也就是帮助自己进一步的理解和学习反射机制. 反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修 ...
- android自定义进度条_Android中的自定义进度栏
android自定义进度条 Custom progress bar in android application gives it a personal touch. In this tutorial ...
- android 滑动取值_Android中滑屏实现
前言: 虽然本文标题的有点标题党的感觉,但无论如何,通过这篇文章的学习以及你自己的实践认知,写个简单的滑屏小 Demo还是justso so的. 友情提示: 在继续往下面读之前,希望您对以下知识点有 ...
最新文章
- select三级联动 怎么删除前一个的_python测试开发django57.xadmin选项二级联动
- 哈利波特 pdf_干货!哈利波特英文原版pdf免费领,(含音频)词汇量大于新概念!...
- div超出部分滚动并且隐藏滚动条
- 【原】UCS-2和UTF-8的互相转换
- mysql数据转存到时序数据库_干货丨如何高速迁移MySQL数据到时序数据库DolphinDB...
- android view设置按钮颜色_Android 酷炫自定义 View:高仿 QQ 窗帘菜单
- hiho1095(二分)
- python中对象排序的两种方式
- Atitit.搜索引擎内容来源解决之道
- 哨兵系列卫星_美国宇航局 quot;哨兵6quot;海平面与气候观测卫星发射任务将于11月进行...
- U8 ActiveX 部件不能创建对象
- ONNXRUNTIME_EXCEPTION : Non-zero status code returned while running Where node. Name:‘Where‘
- 使用LabVIEW进行物体追踪图像处理分析
- 如何写出好文案,不妨看看这篇(上)
- html后代元素选择器,怎么使用html5中的后代选择器?后代选择器的用法详解!
- Spring的Tomcat服务关闭后,Quartz进程无法正常关闭,出现内存泄露
- 圣诞节,1inch狂撒3亿美金红包,币圈大佬在线炫富,我酸了...
- 2016 HCTF web writeup
- 用士兵突击的台词激励一下堕落的自己
- ARC中__bridge, __bridge__transfer, __bridge_retained 关系