不要在精确计算中使用float和double类型
http://blog.csdn.net/androiddevelop/article/details/8478879
一 问题描述
float和double类型不能用于精确计算,其主要目的是为了科学计算和工程计算,它们执行二进制浮点原酸,目的是为了广泛的数值范围上提供较为精确的快速近似计算而精心设计的。但是如果设计钱币之类的计算需要很精确,所以这种情况不能使用float和double,因为要让其精确表示0.1 或者 10的任何负数次方值是不可能的。
二 眼见为实,举例证明:
- // float与double 无法精确表示0.1 或者 10的负次方
- System.out.println( 0.15 - 0.05 ); // 0.09999999999999999
- System.out.println( 2.08f - 3.7f );// -1.6200001
三 举一个现实中会遇到的情况:
一个实际的例子,口袋里面有10元钱,买0.9元的商品十个 , 收银员需要找零1元。计算如下:
- 10 - 0.9 * 10 = 1
代码实现:
- float myMoney = 10.00f;
- float price = 0.9f;
- for (int i = 0; i < 10; i++) {
- myMoney -= price;
- }
- System.out.println( myMoney ); // 1.0000002
结果竟然输出的是1.0000002而非1,可能很多人会认为这也无所谓啊,毕竟仅偏差了0.0000002,但问题是如果前提是进行了1亿笔交易呢?难道你愿意仅仅因为使用了计算机计算这些数据,而损失一部分钱吗?
四 解决办法
1. 使用int 和 long类型,如果小数点以后的值可以忽略不计可以只用这两种类型
2. 对计算结果进行四舍五入
3. 使用BigDecimal类型进行浮点运算
先来看一段代码
- int intValue = 10;
- float floatValue = 0.99999f;
- int count1 = (int) (intValue + floatValue);
- System.out.println("10 + 0.99999 = " + count1); // output 10
- int count2 = (int) (intValue - floatValue);
- System.out.println("10 - 0.99999 = " + count2); // output 9
原本按我个人的理解 10 + 0.99999 = 10.99999 然后转为int类型会进行四舍五入 值为11,而实际结果为10
更深入的分析可以查看
如何解决float和double误差问题呢?可以使用Java中提供的java.math.BigDecimal,不过此类型是不可变的,每次计算都必须新创建一个对象,不适合大量计算
再来看一个舍入误差会出现的问题
- // 10.1 + 0.99*10 = 20
- float f1 = 10.1f;
- float f2 = 0.99f;
- for (int i = 0; i < 10; i++) {
- f1 += f2;
- }
- System.out.println(f1); // 19.999998
解决办法,使用BigDecimal
- BigDecimal count = new BigDecimal("10.1");
- for (int i = 0; i < 10; i++) {
- count = count.add(new BigDecimal("1"));
- }
- System.out.println(count.intValue()); // 20
参考资料:
2. 《Effective Java》 第2版 第48条 如果需要精确的答案,请避免使用float和double
不要在精确计算中使用float和double类型的更多相关文章
- Java中的float、double计算精度问题
java中的float.double计算存在精度问题,这不仅仅在java会出现,在其他语言中也会存在,其原因是出在IEEE 754标准上. 而java对此提供了一个用于浮点型计算的类——BigDeci ...
- C#中对于float,double,decimal的误解
原文:C#中对于float,double,decimal的误解 一直很奇怪C#的预定义数据类型中为什么加了一个decimal,有float和double不就够了吗?今天来挖一挖. 浮点型 如果我们在代 ...
- Effective Java 第三版——60. 需要精确的结果时避免使用float和double类型
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- C#中对于float,double,decimal的误解(转载)
浮点型 Name CTS Type Description Significant Figures Range (approximate) float System.Single 32-bit sin ...
- java中int,float,long,double取值范围,内存泄露
java中int,float,long,double取值范围是多少? 写道 public class TestOutOfBound { public static void main(String[] ...
- MySQL中的float和decimal类型有什么区别
decimal 类型可以精确地表示非常大或非常精确的小数.大至 1028(正或负)以及有效位数多达 28 位的数字可以作为 decimal类型存储而不失其精确性.该类型对于必须避免舍入错误的应用程序( ...
- 关于SQL中数据类型(float和real)和 .NET Framework 中数据类型(float和double)的问题
今天同学写程序遇到一个问题,MSSQL里的数据是 float 类型,在 .NET Framework 中用的时候也转换成 float 类型,结果报错,类型转换异常,明明是相同的类型,为什么会异常 在w ...
- hive 中的float和double
表employees中字段 taxes(税率)用类型float存储 hive> select name, salary, taxes from employees where taxes &g ...
- C语言中关于float和double的输入输出格式
1.对于double类型,输入格式为scanf("%lf %lf", &foo, &bar); 对于float类型,输入格式为scanf("%f %f, ...
随机推荐
- [LeetCode OJ] Sort Colors
Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...
- 如何在本地安装测试ECSHOP 转载
如何在本地安装测试ECSHOP 如何在本地(自己的电脑)上先安装ECShop 一.创建PHP环境 1.下载AppServ 因为ECShop在线网上商店系统是用PHP语言开发的,所以,在本地架设网店之前 ...
- (转)log4j日志级别设置成DEBUG时输出Html代码等问题:
log4j日志级别设置成DEBUG时输出Html代码等问题: 问题: log4j日志级别设置成DEBUG时会输出很多信息,包括一些Html代码 解决方案: log4j的控制是树形,所以在log4j.p ...
- Java学习----Math函数
public class TestMath { public static void main(String[] args) { System.out.println(Math.E); System. ...
- JavaScript H5 Canvas
Canvas 由于浏览器对HTML5标准支持不一致,所以,通常在<canvas>内部添加一些说明性HTML代码,如果浏览器支持Canvas,它将忽略<canvas>内部的HTM ...
- WinForm控件复杂数据绑定常用数据源(对Combobox,DataGridView等控件DataSource赋值的多种方法)
开始以前,先认识一下WinForm控件数据绑定的两种形式,简单数据绑定和复杂数据绑定. 1) 简单数据绑定 简单的数据绑定是将用户控件的某一个属性绑定至某一个类型实例上的某一属性.采用如下形式进行绑定 ...
- qrcode.js插件将你的内容转换成二维码格式
---qrcode.js插件将你的内容转换成二维码格式--- 我之前一直想知道二维码是怎么生成,所以就了解了一下, 最后还是不知道它的原理, 但是,我知道怎么生成. 现在就让我带你制作一个你喜爱的二维 ...
- AS3的数据类型和定义
AS3的数据类型分: 基元数据类型:Boolean int(整数) Number(长的浮点数) unit(很大的正整数) String 复杂数据类型:Arrary Date Error ...
- PHP 常用命令
php常用命令: #输出语句 $ php -r "echo '123' . PHP_EOL;" #执行php脚本文件 $ php -f file.php #查看版本号 $ ph ...
- Source kit service terminated Editor functionality temporarily limited
这下可好. Source kit service terminated Editor functionality temporarily limited 运行以下代码出现了以上的提示...另外,还压根 ...