| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2158 人关注过本帖, 1 人收藏
标题:简单的问题,但自己不会
只看楼主 加入收藏
shamoor
Rank: 2
等 级:论坛游民
帖 子:6
专家分:10
注 册:2011-4-4
收藏
得分:0 
以下是引用pangding在2011-3-25 22:36:02的发言:

说了今天晚上来答,不能食言~

首先你得知道怎么把十进制转成二进制。

手算时要分别转整数和小数。

整数是不断除二,反向取余数:
比如 13 = 8 + 4 + 1,即 2^3 + 2^2 + 2^0。所以二进制是 1101
可用竖式算得,如下:
    1 | 13 (13 除以2 商6 余1)
    0 | 6
    1 | 3
    1 | 2
      | 0
算法是,不断除二,把商写在下面,余数写在左边。(这个不太好打,你就凑合着看把,反正会算就行)
然后从下往上看就是 1101

小数部分是不断乘二,取整数部分。
比如 0.8125 = 0.5 + 0.25 + 0.0625 = 1/2 + 1/4 + 1/16,所以写成二进制是 0.1101
用竖式算是:
    1 | 0.8125 (0.8125 乘以2得1.625,整数部分是1,小数部分是0.625)
    1 | 0.625
    0 | 0.25
    1 | 0.5
      | 0
算法是,不断乘二,把整数部分写在左边,小数部分写在下面。到0为止。
这个是从上往下看的。所以就是 0.1101

此时就有 13.8125 写成二进制就是 1101.1101。


先会这个,再看你那个题。

咱们先算 3.3
3 = 2+1,即是二进制 11,没得说。
0.3:
    0 | 0.3
    1 | 0.6
    0 | 0.2
    0 | 0.4
    1 | 0.8
    1 | 0.6
    ... ...
0.6 又出现了。

这就比较有意思了,虽然 0.3 在十进制里很平常,但在二进制里是无限循环小数。
所以 3.3 是 11.0100110011001....
同理可以算得 1.1 是 1.0001100110011001....

这两个都是无限小数,在计算机这种二进制的世界里显然无法精确表示。


IEEE 标准里(好像是754标准吧,是个规定浮点运算相关的标准)规定了浮点数的表示方法。
统一用类似科学计数法的方法表示:m * 2^n。
m 称为尾数(Fraction),n 称为阶数或者指数(exponent),还有一个符号位来表示正负。
并要求要调整指数,比如 1101.1101 * 2^0 要写成 1.1011101 * 2^3。此时指数就是 3,当然要用二进制的11;尾数是 1.1011101。由于这么一移,整数部分必然是用1开头的,没必要多浪费一位。所以尾数部分不储存首1。即 m 是 1011101。

当然情况没这么简单,还可能有的数是 0.001,就得写成 1 * 2^-3。这么一来,指数又得有正负,为了避免这个,指数还要用偏移码的方法表示。
标准里规定的比较详细。我这说的叫正规浮点数,还有非正规的。还有用来表示正负无穷大的(INF),表示无意义值的(NaN),无意义值又有很多种类,用于表示不同的错误,等等。我不详细介绍了。


具体来说:
32位(4字节的,相当于 float)的浮点数,有1位符号位,8位指数位,23位尾数位。
64位(8字节的,如double),有1位符号,11位指数,52位尾数。
好像标准里还有16位的,我记不得了。有兴趣的自己查。

既然尾数有限,就存不下无限小数,存不下的值就抛弃了。
至于你问为什么除出来是 2.99999 这个其实可以算,但我实在不想算了。
乘除法的机器算法用的是位移加减,你可以自己手算。查下资料,把那52位数写出来,先指数对齐,再位移最多不超过52次,做减法,就能得到。


我觉得楼主大概知道这么多,也不是那么疑惑了。这些知识在计算机组成原理里都有讲。
会不会这些,对 C 这种高级语言来说不是那么太重要了。同样的算法在不同的编译器上,不同的系统上,不同的硬件上,跑下来的值在小数点很后面的几位有点微小的偏差是很正常的事情。(虽然 GNU 的有些文档,也指出这种行为是它们软件的BUG,不过他们说了这种 BUG 改善不了)

不要太纠结。一般来说把低精度的往高数度的转,如 int 转 double 是没问题的,相反的转法一般是不可取,精度损失太大。
像这个例子,根据 2楼 提供的数据,本来 double 算下来,誤差也就是几百亿分之一,结果一转变成1了。好的编译器,应该在这种情况给中等级别以上的警告提示。

硬件方面我也只是会 intel 的 80x86 的架构。别的不是很清楚,不过这个工程标准规定的东西,肯定什么设备都一样。
太牛了!今天值了!
2011-04-04 19:31
yangfanconan
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:10
帖 子:397
专家分:541
注 册:2009-9-22
收藏
得分:0 
犀利点好。
2011-04-07 12:58
肖付
Rank: 2
等 级:论坛游民
帖 子:53
专家分:24
注 册:2010-9-11
收藏
得分:0 
回复 21楼 shamoor
兄台犀利啊。。
膜拜,膜拜!
2011-04-09 11:52
小鱼o号
Rank: 1
等 级:新手上路
帖 子:13
专家分:2
注 册:2011-1-29
收藏
得分:0 
今天看到了,但还是说,经典啊
2011-04-09 22:37
Crystal_CL
Rank: 1
等 级:新手上路
帖 子:4
专家分:1
注 册:2011-4-10
收藏
得分:0 
俺也是新手,俺也没看懂。。。。.......
到底是咋回事啊?
2011-04-10 10:32
wangjunit
Rank: 1
等 级:新手上路
帖 子:2
专家分:2
注 册:2011-4-12
收藏
得分:0 
我运行楼主代码 结果是3
2011-04-12 17:20
守墨
Rank: 1
等 级:新手上路
帖 子:5
专家分:1
注 册:2011-4-15
收藏
得分:0 
,凑下热闹,新手···
2011-04-15 22:31
proluo
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2011-4-16
收藏
得分:0 
12楼很强大啊!
2011-04-17 11:32
xjzxylj
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:86
专家分:113
注 册:2011-4-18
收藏
得分:0 
我想是数据问题吧,上面都是double,商是int。

淫一手湿,简单;难的是,淫一被子湿。(富有诗意,此处抄袭)
2011-04-20 15:48
棉雨
Rank: 5Rank: 5
等 级:职业侠客
帖 子:174
专家分:368
注 册:2011-4-22
收藏
得分:0 
我又学到一点东西。
2011-04-23 00:08
快速回复:简单的问题,但自己不会
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.012079 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved