**当你在写一个电商网站的时候,你可能会给你的商品标价1.99,10.9这样的价格来吸引顾客.我应该用浮点数float/double来储存它们,当我的顾客购买商品的时候,从他们的账户里扣费,使用整型是不可能的.你可能会这么想.

**如果你的顾客账号里的钱刚好是1950.00,5001.00这样的整元,那么恭喜你,你的想法是没有错的.但是一旦有一位顾客的账号里还有若干毛,若干分钱没花完,那你的程序就会得到一个错误的数值!很无奈的是,你无法通过报错信息找到它,如果你已经用浮点型float/double来计算,那么你将很难发现这个错误!

**例如,有这样一个业务需要处理:顾客有500.05块钱,你的商品定价19.9元.

        double d1 = 500.05;
double d2 = 19.9;
double d3 = d1 - d2;

**你可能想顾客钱包里应该还有480.15元.但是你得到的结果是480.15000000000003元.虽然相差很少,但是日积月累或者当你在经营一个亿万数据的网站,这将是个极大的BUG!

那么我们该怎么解决这个问题呢?

**如果你要解决某个问题,那么你首先要知道问题出现在哪.这是我写程序的准则那么问题出现在哪呢?经过百度+摸索,发现十进制数的二进制表示可能不够精确.浮点数值没办法用十进制来精确表示的原因要归咎于CPU表示浮点数的方法。这样的话您就可能会牺牲一些精度,有些浮点数运算也会引入误差。以上面提到的情况为例,480.15的二进制表示并非就是精确的480.15。反而最为接近的二进制表示是 480.15000000000003。原因在于浮点数由两部分组成:指数和尾数。

Java中的简单浮点数类型float和double不能够进行运算。不光是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。 这个问题相当严重,如果你有9.999999999999元,你的计算机是不会认为你可以购买10元的商品的。 在有的编程语言中提供了专门的货币类型来处理这种情况,但是Java没有。这个问题有两种方案.

1.你将得到的数经过放大n个整数倍后再除以n个整数倍.它的原理和java进制转换的原理相同.

2.不要用浮点数double/float进行计算,选择BigDecimal进行精确运算.

在使用BigDecimal类来进行计算的时候,主要分为以下步骤:

a、用float或者double变量构建BigDecimal对象。

b、通过调用BigDecimal的加,减,乘,除等相应的方法进行算术运算。

c、把BigDecimal对象转换成float,double,int等类型。

BigDecimal能够很好地对浮点数进行运算.但是他的计算过程相对来说十分麻烦,而且因为每次计算都要创建一个实例,十分消耗资源.以下举例说明它的计算过程

—->>>>

    BigDecimal b1 = new BigDecimal(Double.toString(500.05));
BigDecimal b2 = new BigDecimal(Double.toString(19.9));
System.out.println(b1.subtract(b2));
****要注意的是,如果你直接在BigDecimal b1 = new BigDecimal(Double.toString(500.05));里面写浮点数,依旧会出现精确度的偏差!

****最后,感谢同学魏勇/黎裕锦和我分享这个问题,如果后续有更加优秀的解决方案,我也会及时贴上来!**

有趣的Java之调皮的浮点数的更多相关文章

  1. java中float/double浮点数的计算失精度问题(转)

    如果我们编译运行下面这个程序会看到什么? public class Test  {    public static void main(String args[]) {                ...

  2. Java比较两个浮点数

    浮点数的基本数据类型不能用==比较,包装数据类型不能用 equals 比较 浮点数的表示 在计算机系统中,浮点数采用 符号+阶码+尾数 进行表示.在Java中,单精度浮点数float类型占32位,它的 ...

  3. 怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏

    这么说吧,在我眼里,Java 就是最流行的编程语言,没有之一(PHP 往一边站).不仅岗位多,容易找到工作,关键是薪资水平也到位,不学 Java 亏得慌,对吧? 那可能零基础学编程的小伙伴就会头疼了, ...

  4. Java如何正确比较浮点数

    看下面这段代码,将 d1 和 d2 两个浮点数进行比较,输出的结果会是什么? double d1 = .1 * 3; double d2 = .3; System.out.println(d1 == ...

  5. 很有趣的Java分形绘制

    部分与整体以某种形式相似的形,称为分形. 首先我们举个例子:        我们可以看到西兰花一小簇是整个花簇的一个分支,而在不同尺度下它们具有自相似的外形.换句话说,较小的分支通过放大适当的比例后可 ...

  6. 记一个有趣的Java OOM!

    原文:https://my.oschina.net/u/1462914/blog/1630086 引言 熟悉Java的童鞋,应该对OOM比较熟悉.该类问题,一般都比较棘手.因为造成此类问题的原因有很多 ...

  7. 有趣的java小项目------猜拳游戏

    package com.aaa; //总结:猜拳游戏主要掌握3个方面:1.人出的动作是从键盘输入的(System.in)2.电脑是随机出的(Random随机数)3.双方都要出(条件判断) import ...

  8. Java正则表达式-匹配正负浮点数

    记录缘由: 公司项目需要从xml中获取标识为NUMBER的字符串,将之存入数据库中,存入的列的类型即为NUMBER.当遇到非数字时,原实现是通过异常: String plainValue = null ...

  9. 浮点数转换为人名币读法字符串(JAVA)

    /*<java疯狂讲义>浮点数转换为人名币读法字符串这个用例,感觉没有考虑零的情况*/ import java.util.Arrays; public class Num2Rmb { pr ...

随机推荐

  1. cssBase.css你应该有一个

    @charset "utf-8"; /*! * @名称:base.css * @功能:1.重设浏览器默认样式 * 2.设置通用原子类 */ /* 防止用户自定义背景颜色对网页的影响 ...

  2. vue-music 关于Search(搜索页面)--上拉加载

       建立搜索框组件页面,searchBox,组件接受一个可以自定义传入的placeholder 属性.input v-model 双向绑定数据关联到query 中, 在created中监听 quer ...

  3. phpstorm如何进行文件或者文件夹重命名

    1.phpstorm的重构 1.1重命名 在phpstorm中,右键点击我们要进行修改的文件,然后又一项重构,我们就可以进行对文件的重命名. 接下来点击重命名进行文件或者文件夹的重新命名. 在框中输入 ...

  4. mysql-错误备查

    转载请注明:仰望大牛的小清新   http://www.cnblogs.com/luruiyuan/ 这个文章的主要目的是总结自己的作死经历,以备查找 1. Ubuntu MySQL 服务的启动/停止 ...

  5. (转)求质数算法的N种境界[1] - 试除法和初级筛法

    ★引子 前天,俺在<俺的招聘经验[4]:通过笔试答题能看出啥?>一文,以"求质数"作为例子,介绍了一些考察应聘者的经验.由于本文没有政治敏感内容,顺便就转贴到俺在CSD ...

  6. 解决Linux环境下安装xampp之后外部无法连接MySQL的问题

    在Linux系统下,开发PHP一般都是LAMP环境,对于开发环境来讲,没有必要花太大精力去单独配置LAMP环境,采用xampp一键安装包是一个很好的方式.在Linux系统上安装xampp的过程这里就不 ...

  7. [BZOJ4861][BJOI2017]魔法咒语(AC自动机+矩阵优化DP)

    4861: [Beijing2017]魔法咒语 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 217  Solved: 105[Submit][Sta ...

  8. 一个简单的Spring程序

    首先,要用Eclipse开发Spring程序,需要安装Spring插件并重启Eclipse 具体操作: 新建java Project后,导入需要使用的包(提前下好Spring),Spring包包含6个 ...

  9. ConcurrentHashMap(Java8)源码分析

    1. 常量.成员变量 private static final int MAXIMUM_CAPACITY = 1 << 30; // 和HashMap一样 private static f ...

  10. 怎么提高DB的效率

    主要从4方面,提高db的效率: 1,建立索引:(巴东) 2,多线程: 3,锁的范围(表级,行级...) 4,内存数据库