double转换为int以及浮点型相加损失精度问题
最近在做支付相关模块的业务,数据库字段却使用的是double类型,其实也行,只要计算不在sql语句中进行,也是没有问题的。
预先的类属性设置的是Double类型,自己算的时候发现小数相加会出现损失精度的情况
如下情形
@Test
public void testDouble(){
Double [] arr = {39.9d,50d,198d,39.9d};
Double verify = 0d;
for (Double aDouble : arr) {
verify += aDouble ;
}
System.out.println(verify);
}
输出的结果是:327.79999999999995 理应为:328
待着疑惑试了下js

一看是一个效果,精度都会缺失。百度了下,解释如下
- 符号位(Sign): 0代表正,1代表为负
- 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
- 尾数部分(Mantissa):尾数部分
实数符号位 指数符号位 指数位 有效数位
但是,在将十进制浮点数转换为二进制浮点数时,小数的二进制有时也是不可能精确的,就如同十进制不能准确表示1/3,二进制也无法准确表示1/10,而double类型存储尾数部分最多只能存储52位,于是,计算机在存储该浮点型数据时,便出现了精度丢失。
例如,11.9的内存存储大约为:1011. 1110011001100110011001100...
而在进行浮点类数据计算的时候,浮点参与计算,会左移或右移n位,直到小数点移动到第一个有效数字的右边。于是11.9在转化为二进制后 小数点左移3位,就得到1. 011 11100110011001100110(精度丢失2)
于是最终浮点型运算出现了精度丢失误差。
解决方式,java中可以使用 BigDecimal 来解决
@Test
public void test3(){
System.out.println(0.11+2001299.32);//非精确的输出
BigDecimal bigDecimal1 = new BigDecimal(Double.toString(0.11));
BigDecimal bigDecimal2 = new BigDecimal(Double.toString(2001299.32));
System.out.println(bigDecimal1.add(bigDecimal2));//精确的输出
}
这种方式可以解决,并且很完美,但是还有一种方式比较容易些,毕竟是金额,小数位只有两位,可以先将其扩大100倍,再进行计算,计算完毕之后再除100,也可以解决(这么不要脸的方式也只有我这么low的程序员使用了),惭愧,出错了。
在计算的过程总遇到double转int的情况,总结了下实现的方式
Double d = 1.7d;
@Test
public void test1(){
// 这样会报错,因为double转换为字符串之后有.
System.out.println(Integer.parseInt(d.toString()));
}
@Test
public void test2_1(){
// double 类型可以直接转为int类型
double dd = 1.1;
int ddd = (int)dd;
System.out.println(ddd);
}
@Test
public void test2_2(){
// 可以通过强转进行转换,Double是包装类,不能直接进行强转,可以拆箱之后再次强转。
int aa = (int)(Double.parseDouble(d.toString()));
System.out.println(aa);
}
@Test
public void test3(){
// 这种方式最为简单
System.out.println(d.intValue());
}
@Test
public void test4(){
DecimalFormat format1 = new DecimalFormat("#");
String s = format1.format(d);
System.out.println(s);
}
@Test
public void test5(){
DecimalFormat format1 = new DecimalFormat("#.#");
String s = format1.format(1.35);
System.out.println(s);
}
@Test
public void test6(){
DecimalFormat format1 = new DecimalFormat("0.000");
String s = format1.format(1.35);
System.out.println(s);
}
DecimalFormat 要四舍五入需要加上 setRoundingMode(RoundingMode.HALF_UP); 网上是这么说的,但是自己测试默认就会四舍五入
特殊字符说明
“0” 指定位置不存在数字则显示为0 123.123 ->0000.0000 ->0123.1230
“#” 指定位置不存在数字则不显示 123.123 -> ####.#### ->123.123
“.” 小数点
“%” 会将结果数字乘以100 后面再加上% 123.123 ->#.00->1.3212%
嗯,就这么个坑了。
double转换为int以及浮点型相加损失精度问题的更多相关文章
- 从‘void*’到‘int’的转换损失精度
在CentOS6.2 64位下编译一下代码,不通过,提示 ./11_2.cpp: In function ‘int main(int, char**)’:./11_2.cpp:28: 错误:从‘voi ...
- C++中将string类型转换为int, float, double类型 主要通过以下几种方式:
C++中将string类型转换为int, float, double类型 主要通过以下几种方式: # 方法一: 使用stringstream stringstream在int或float类型转换为 ...
- double类型转换为int类型四舍五入工具类
package com.qiyuan.util; import java.math.BigDecimal; import java.text.DecimalFormat; public class G ...
- pandas把'<m8[ns]'类型转换为int类型进行运算
工作中经常碰到两列数据为date类型,当这两列数据相减或者相加时,得到天数,当运用这个值进行运算会报错:ufunc true_divide cannot use operands with types ...
- java把含小数点的数字字符串转换为int类型
String num ="1.00"; int abc =Double.valueOf(num).intValue();//转换为Int类型
- string型的“600.000”如何转换为int型
string型的“600.000”怎么转换为int型?为什么我用int.parse不能转换? ------解决方案--------------------int.Parse("600.000 ...
- Linux C 知识 char型数字转换为int型 int型 转换为Char
前言 在九度oj做acm的时候,经常会遇到了char类型和int类型相互转化的问题,这里进行一下总结.今后,可能会多次更新博客,因为半年做了很多总结,但是都是保存在word文档上了,现在开始慢慢向CS ...
- int([x[, base]]) : 将一个字符转换为int类型,base表示进制
int([x[, base]]) : 将一个字符转换为int类型,base表示进制 >>> int(-12) -12 >>> int(-12.00) -12 > ...
- android十六进制颜色代码转换为int类型数值
android开发中将十六进制颜色代码转换为int类型数值方法:Color.parseColor("#00CCFF")返回int数值;
随机推荐
- 最大m段子段和
hdu1024 最大m子序列和 给定你一个序列,让你求取m个子段(不想交的子段)并求取这m个子段和的最大值 从二维开始来看dp[i][j]表示取第j个数作为第i个子段的元素所得到的前i个子段和的最大值 ...
- JavaScript中的工厂函数
所谓工厂函数,就是指这些内建函数都是类对象,当你调用他们时,实际上是创建了一个类实例. 在学习jQuery的时候,我们经常会看到“工厂函数”这个概念,那么究竟什么是“工厂函数”呢?我们来看看概念,“所 ...
- 判断闰年的Java算法
判断方法 普通年能被4整除且不能被100整除的为闰年. 世纪年能被400整除的是闰年 对于数值很大的年份,这年如果能整除3200,并且能整除172800则是闰年.如172800年是闰年,86400年不 ...
- WPF 右上角带数字的按钮
效果如图所示 三种方案, 1:不改控件模版,布局实现,死开 2:改button模版,利用附加属性,附加附加属性,功能多了话,不利于拓展 3:继承button,添加依赖属性,接下来是这种 1:新建类 为 ...
- ASP.NET MVC一次删除多笔记录 V2.0
前一段时间Insus.NET有写一篇<ASP.NET MVC一次删除多笔记录>http://www.cnblogs.com/insus/p/6241186.html 可以前往去看看. 觉得 ...
- 常见配置redis.conf介绍
参数说明redis.conf 配置项说明如下:1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 daemonize no2. 当Redis以守护进程方式运行 ...
- [转]高端又易学的vbs表白程序了解一下
第一个. 打开txt文件,复制以下代码粘贴进去(可以修改中文部分,其它代码不要动!).保存并关闭txt文件. msgbox("做我女朋友好吗?") msgbox("房产证 ...
- Linux学习笔记-基本操作3
1. vim编辑器的使用2. gcc编译器3. 静态库的制作 -- lib4. 动态库的制作 -- dll vi -- vimvim是从vi发展过来的一款文本编辑器vi a.txt前提: 安装了 ...
- 【ElasticSearch】:Windows下ElasticSearch+版本安装head
概述 elasticsearch-head,之前插件plugin方式已废弃,现已改为nodejs的NPM安装,独立WEB服务方式. elasticsearch-head网址:https://githu ...
- python学习笔记11-文件操作方法
f=open("1.txt","r",encoding='utf-8') # a=f.readline() print(a) #光标会移动 下面两者结果不一样 ...