精度问题讨论

zdjray 2007-08-27 08:54:19
当作散分吧

今天一直在想这个问题
不明白问什么会有奇怪的结果
找了书,查了资料
深入理解计算机系统都搬出来看了
想了很多道理都不能解释的通

System.out.println(1.20-1.10);
System.out.println(1.30-1.10);
System.out.println(1.40-1.10);
System.out.println(1.50-1.10);
System.out.println(1.60-1.10);
System.out.println(1.70-1.10);
System.out.println(1.80-1.10);
System.out.println(1.90-1.10);
System.out.println(2.00-1.10);
System.out.println(2.10-1.10);

打印结果:
0.09999999999999987
0.19999999999999996
0.2999999999999998
0.3999999999999999
0.5
0.5999999999999999
0.7
0.7999999999999998
0.8999999999999999
1.0

按照官方解释是说1.10这个数字不能被精确表示成为一个double,因此它被表示成为最接近它的double值(从而会造成一堆数字)

我接受了,但是大家可以看到上面的结果是0.5,0.7和1.0都还是很好的结果
而且我在想其实像1.10这样的数字实在是太多了,从统计上来讲有一大半都是不能被有限二进制表示的,难道这些都要造成这么复杂的结果?

关键是这里打印出来了0.5,0.7和1.0
经过实验,人为造出了这些数字的有一串的形式,列举如下:
System.out.println(2.20-1.70);
System.out.println(2.20-1.50);
System.out.println(2.20-1.20);
System.out.println(1.0000000000000003);

打印结果如下:
0.5000000000000002
0.7000000000000002
1.0000000000000002
1.0000000000000002

从而消除了0.5,0.7和1.0是因为可以被有限表示而有很好结果的可能
(最后一个是该数的最近表示,作为参考)

我暂时的问题就在这里了
假如说是1.10的问题,为什么0.5,0.7和1.0却能够出现?

欢迎大家讨论~~
...全文
461 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
codeartisan 2007-10-12
  • 打赏
  • 举报
回复
8楼的回复来自百度贴吧,因为我搜索过,所以我知道。

Ctrl+C和Ctrl+V居然得了30分。。
logqq 2007-10-09
  • 打赏
  • 举报
回复
从来没有想地这个问题哦~~

谢谢了~~
eBayFellow 2007-09-03
  • 打赏
  • 举报
回复
楼上怎么连基本的素质都没有?
先看清楼主讲的什么吧!!!
zdjray 2007-09-03
  • 打赏
  • 举报
回复
diggywang(Miner Lover!)
你说的其实都对
只是我在问题中已经讲清楚了

请参看这一句话:
按照官方解释是说1.10这个数字不能被精确表示成为一个double,因此它被表示成为最接近它的double值(从而会造成一堆数字)

至于用BigDecimal确实在实践中是很有必要的,只是我提出这个问题并不是寻求解决方案
而且这样问题的解决方案网上应该有很多了,也不必发帖

在这里我不明白的是为什么有的结果可以表示成很简单的数有的却很复杂(虽然它们都有不精确的操作数)?
现在得到比较合理的解释我个人认为是我上面的最后一次回复
谢谢~~
diggywang 2007-09-03
  • 打赏
  • 举报
回复
连java中的基本精度计算都不懂!
所有的加减乘除计算都要用BigDecimal!!!不然银行系统早就趴下了!
crz521 2007-09-03
  • 打赏
  • 举报
回复
up ~~
bushuang 2007-09-03
  • 打赏
  • 举报
回复
结贴给分吧
diggywang 2007-09-03
  • 打赏
  • 举报
回复
我当然知道,楼上的也麻烦看一下标题。
先道个歉,上面的语气确实不太好,Sorry。不过我碰到过太多的人大谈java精度问题,我是觉得没有这个必要谈论。只要牢记一点就好,在java中所有涉及到大数及高精度的运算,请使用BigDecimal,并且BigDecimal的参数,必须是String类型,希望baobao28(瓜瓜) 也知道。Sun官方也明确在文章和书籍中指出:float,double之类的运算只适合在科学计算和工程计算时使用,在商业计算中要使用BigDecimal。
要知道float,double运算后为什么会有偏差,请先看一下这篇基础文章:
http://java.ccidnet.com/art/3737/20060626/589429_1.html
概况一句话就是:not all numbers can be represented with a certain amount of bits!This is a fundamental limitation of digital computers
zdjray 2007-09-02
  • 打赏
  • 举报
回复
准备结贴了吧
最近找到一个比较好的说法
但是我还想让别人看一看这个说法,所以先放这里两天~~

以2.2-1.2为例
2.2转为二进制后,比2.2略大一些,但近似还是2.2
1.2转为二进制后,比1.2略小一些
两者之差,将两个差值累加起来,导致结果相对于1来说?
更接近那个带尾巴的数字
zephyr_cc 2007-09-02
  • 打赏
  • 举报
回复
有什么研究结果了?
zdjray 2007-09-02
  • 打赏
  • 举报
回复
有人吗?
zdjray 2007-08-29
  • 打赏
  • 举报
回复
瞬间被水淹没~~
fengran22 2007-08-28
  • 打赏
  • 举报
回复
晕呼呼..
livan1038 2007-08-28
  • 打赏
  • 举报
回复
都是進制與精度問題,小頂一下
baobao28 2007-08-28
  • 打赏
  • 举报
回复
不知道是不是我调试错误,测试如下:
BigDecimal b1=new BigDecimal(1.20-1.10);
System.out.println(b1);

double b2=1.20-1.10;
System.out.println(b2);

float b3=(float) (1.20-1.10);
System.out.println(b3);

输入结果如下:
0.0999999999999998667732370449812151491641998291015625
0.09999999999999987
0.1
beibeiG 2007-08-28
  • 打赏
  • 举报
回复
以前遇到精度问题就一直没弄明白
malligator 2007-08-28
  • 打赏
  • 举报
回复
如果两个都是偏小误差,而且相减的结果可以准确表示,就是准确的结果;
如果一个是偏小误差另一个不是,结果就是近似的:或多或少,看偏小的做被减数还是减数了
  • 打赏
  • 举报
回复
有一本叫作《Java数值方法》(Java Number Cruncher: The Java Programmer's Guide to Numerical Computing)的书中第一章就很详细地讲述了浮点数运算的精度问题。在这里推荐一下,很不错的一本书。
zdjray 2007-08-28
  • 打赏
  • 举报
回复
zephyr_cc() 说的很有道理

我其实也想过这样误差相减的原因
只是没有做这么深入的查证
辛苦了

我会做进一步的验证,尽早把结果贴上来~
dddpp 2007-08-28
  • 打赏
  • 举报
回复
晕乎乎
加载更多回复(8)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧