BigDecimal _0_1 = new BigDecimal(0.1);
BigDecimal x = _0_1;
for(int i = 1; i <= 10; i ++) {
System.out.println(i+" x 0.1 is "+x+", as double "+x.doubleValue());
x = x.add(_0_1);
}

输出:

0.1000000000000000055511151231257827021181583404541015625, as double 0.1
0.2000000000000000111022302462515654042363166809082031250, as double 0.2
0.3000000000000000166533453693773481063544750213623046875, as double 0.30000000000000004
0.4000000000000000222044604925031308084726333618164062500, as double 0.4
0.5000000000000000277555756156289135105907917022705078125, as double 0.5
0.6000000000000000333066907387546962127089500427246093750, as double 0.6000000000000001
0.7000000000000000388578058618804789148271083831787109375, as double 0.7000000000000001
0.8000000000000000444089209850062616169452667236328125000, as double 0.8
0.9000000000000000499600361081320443190634250640869140625, as double 0.9
1.0000000000000000555111512312578270211815834045410156250, as double 1.0

原因:

Most answers here address this question in very dry, technical terms. I'd like to address this in terms that normal human beings can understand.

Imagine that you are trying to slice up pizzas. You have a robotic pizza cutter that can cut pizza slices exactly in half. It can halve a whole pizza, or it can halve an existing slice, but in any case, the halving is always exact.

That pizza cutter has very fine movements, and if you start with a whole pizza, then halve that, and continue halving the smallest slice each time, you can do the halving 53 times before the slice is too small for even its high-precision abilities. At that point, you can no longer halve that very thin slice, but must either include or exclude it as is.

Now, how would you piece all the slices in such a way that would add up to one-tenth (0.1) or one-fifth (0.2) of a pizza? Really think about it, and try working it out. You can even try to use a real pizza, if you have a mythical precision pizza cutter at hand. :-)


Most experienced programmers, of course, know the real answer, which is that there is no way to piece together an exact tenth or fifth of the pizza using those slices, no matter how finely you slice them. You can do a pretty good approximation, and if you add up the approximation of 0.1 with the approximation of 0.2, you get a pretty good approximation of 0.3, but it's still just that, an approximation.

For double-precision numbers (which is the precision that allows you to halve your pizza 53 times), the numbers immediately less and greater than 0.1 are 0.09999999999999999167332731531132594682276248931884765625 and 0.1000000000000000055511151231257827021181583404541015625. The latter is quite a bit closer to 0.1 than the former, so a numeric parser will, given an input of 0.1, favour the latter.

(The difference between those two numbers is the "smallest slice" that we must decide to either include, which introduces an upward bias, or exclude, which introduces a downward bias. The technical term for that smallest slice is an ulp.)

In the case of 0.2, the numbers are all the same, just scaled up by a factor of 2. Again, we favour the value that's slightly higher than 0.2.

Notice that in both cases, the approximations for 0.1 and 0.2 have a slight upward bias. If we add enough of these biases in, they will push the number further and further away from what we want, and in fact, in the case of 0.1 + 0.2, the bias is high enough that the resulting number is no longer the closest number to 0.3.

In particular, 0.1 + 0.2 is really 0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 = 0.3000000000000000444089209850062616169452667236328125, whereas the number closest to 0.3 is actually 0.299999999999999988897769753748434595763683319091796875.

总结:

这也解释通了0.1可以精确输出,0.3也可以精确输出 ,而0.1+0.1+0.1输出 0.30000000000000004;因为0.1 + 0.2实际上是0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 = 0.3000000000000000444089209850062616169452667236328125,而最接近0.3的数字实际上是0.299999999999999988897769753748434595763683319091796875。

    @Test
public void test() {
double a = 0.1;
double b = 0.3;
System.out.println("a:"+a);
System.out.println("b:"+b);
System.out.println("a+a+a:"+(a+a+a)); } a:0.1
b:0.3
a+a+a:0.30000000000000004

参考: https://stackoverflow.com/questions/588004/is-floating-point-math-broken

    https://stackoverflow.com/questions/26120311/why-does-adding-0-1-multiple-times-remain-lossless?noredirect=1

Float精度丢失的更多相关文章

  1. iOS项目double、float精度丢失解决办法

    描述 在iOS项目中老是遇到double.float精度丢失的问题 PS: NSString * jsonStr = @"{\"9.70\":9.70,\"67 ...

  2. java防止double和float精度丢失的方法

    在浮点数当中做运算时经常会出现精度丢失的情况,如果做项目不作处理的话会对商家造成很大的影响的.项目尤其是金融相关的项目对这些运算的精度要求较高. 问题原因:首先计算机进行的是二进制运算,我们输入的十进 ...

  3. java中double和float精度丢失问题

    为什么会出现这个问题呢,就这是java和其它计算机语言都会出现的问题,下面我们分析一下为什么会出现这个问题:float和double类型主要是为了科学计算和工程计算而设计的.他们执行二进制浮点运算,这 ...

  4. java中double和float精度丢失问题及解决方法

    在讨论两位double数0.2和0.3相加时,毫无疑问他们相加的结果是0.5.但是问题总是如此吗? 下面我们让下面两个doubles数相加,然后看看输出结果: @Test public void te ...

  5. float精度丢失的问题

    在做IPTV的时候,遇到以下这个问题: 现有一个float型数据,以下代码打印输出: float n = 40272.48f; System.out.println(new Double(n * 10 ...

  6. mysql float 精度丢失

    mysql 中保存了字段 float s=0.3 直接执行sql 查出来是 0.3 但是JPA 执行查询结果是 0.2999 换成decimal 就可以

  7. [ JAVA编程 ] double类型计算精度丢失问题及解决方法

    前言 如果你在测试金融相关产品,请务必覆盖交易金额为小数的场景.特别是使用Java语言的初级开发. Java基本实例 先来看Java中double类型数值加.减.乘.除计算式实例: public cl ...

  8. Java:利用BigDecimal类巧妙处理Double类型精度丢失

    目录 本篇要点 经典问题:浮点数精度丢失 十进制整数如何转化为二进制整数? 十进制小数如何转化为二进制数? 如何用BigDecimal解决double精度问题? new BigDecimal(doub ...

  9. iOS - Json解析精度丢失处理(NSString, Double, Float)

    开发中处理处理价格金额问题, 后台经常返回float类型, 打印或转成NSString都会有精度丢失问题, 因此使用系统自带的NSDecimalNumber做处理, 能解决这问题:经过测试其实系统NS ...

随机推荐

  1. PHP的取整函数

    PHP的取整函数有四个,分别是ceil.floor.round和intval,下面对它们进行一一介绍: 1. ceil(x):向上舍入为最接近的整数. 返回不小于 x 的下一个整数,x 如果有小数部分 ...

  2. 正则表达式&常用JS校验

    符号 含义 ^ 以什么开头 $ 以什么结束 * 任意个(包括0个) + 至少一个 ? 没有或一个 {a,b} a-b个 {a} 正好a个 {a,} 至少a个 | 或 . 任意字符 [] 方括号内的任意 ...

  3. 简易RPC框架-上下文

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  4. .10-Vue源码之Watcher(1)

    上一节最后再次调用了mount函数,我发现竟然跳到了7000多行的那个函数,之前我还说因为声明早了被覆盖,看来我错了! 就是这个函数: // Line-7531 Vue$3.prototype.$mo ...

  5. WinForm 菜单控件

    一:MenuStrip 菜单条 MenuStrip 是应用程序菜单条的容器. 二:ToolStripMenuItem 像上面图中, 文件 格式 等这些菜单当中的一级菜单以及文件中的 新建 打开 分割条 ...

  6. velocity的基础使用

    velocity的基本使用要求:掌握jsp的jstl技术,因为velocity的用法和jstl非常相似.语法上差别不大,但是velocity的示例明显比jstl少,解释也少,所以使用velocity必 ...

  7. Game

    Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  8. Python 判断是否为质数或素数

    一个大于1的自然数,除了1和它本身外,不能被其他自然数(质数)整除(2, 3, 5, 7等),换句话说就是该数除了1和它本身以外不再有其他的因数. 首先我们来第一个传统的判断思路: def handl ...

  9. eclipse禁用svg文件Validation

    1.打开window>preferences>validation找到xml validator 2.点击xml validator最右侧的按钮打开xml校验规则窗口,选中exclude ...

  10. font-face 在 Firefox无法正常工作问题

    @font-face存在的问题: 1.不同浏览器支持不同格式 2.Firefox默认情况下不允许跨域font-face,除非你可以添加“Access-Control-Allow-Origin” hea ...