打印

一个四舍五入的问题,大家帮忙看看

[复制链接]
楼主: fushaobing
手机看帖
扫描二维码
随时随地手机跟帖
41
yewuyi| | 2010-10-9 10:44 | 只看该作者 回帖奖励 |倒序浏览
2楼yewuyi方法是可行的,难道LZ的x,y不是整形,如果是整形的话,计算机计算x*100/y是要取整的,
hwwyhy 发表于 2010-10-9 10:24



要按照LZ那种互相矛盾的要求来说,2楼的方法确实是有问题的。

其实,这个问题本身就有一定的悖论,4舍5入是有前提的,无前提的4舍5入也是有问题的,例如0.499,你说这个值多少是多少?

无前提的4舍5入的话,则可以是1,也可以是0.5,还可能是0.4

使用特权

评论回复
42
hwwyhy| | 2010-10-9 10:48 | 只看该作者
恩,是的,这就要求一个精度了,精度越高如果不用浮点的话,计算量就要越大

使用特权

评论回复
43
bald| | 2010-10-9 11:44 | 只看该作者
这是一个复合运算的误差传递问题。
无论采用什么算法,只要中间过程有舍有入,其运算结果的最后一位必然都是可疑的。
采用半进位方法提高运算精度,一般只针对单一运算。
有一个办法可以提高复合运算的精度,就是将所有的源数据都乘以适当的倍数,最后的运算结果做除以相同的因子后做取舍,不过这也仅是0.51、0.501、0.500。。。001之间的区别。比如说34.49999999仍然避免不了被判读为34的结果。因此这种方法只是减小了判别出错的几率,可是相应的代价也是相当大的。

使用特权

评论回复
44
fushaobing|  楼主 | 2010-10-9 17:54 | 只看该作者
to yewuyi:
你没有看懂我的要求,解决不了问题,就不要说什么“伪命题”了?
我后面说过了,“60-23*10/9=34.44444444444444”是在草稿纸上的验算过程,不是在MCU上的执行过程。
当x=23,y=9时,正确结果应该是34。如果你的程序计算结果是35,就是不对的。不知道你能不能理解这一点。

“32楼”说到了点子上。
不知道yewuyi有没有看懂“32楼”的话。
如果2楼的答案是正确的,我根本不会发这个帖子出来。

这个问题我不是没有解决,我在17楼给出了我的做法。只是我觉得这个问题有点意思,所以拿出来和大家讨论一下。

老实说,对于说话不经过大脑,却三番两次口出不逊的人,我的自尊心真的受到了伤害。

使用特权

评论回复
45
fushaobing|  楼主 | 2010-10-9 18:04 | 只看该作者
to ZALIN:
谢谢你的解释。
我会用穷举的方法验证你在“7楼”给出的公式。但我的水平有限,需要一点时间。

to 32楼:
谢谢你。你说到问题的点子上了。我在17楼的处理就是专门把“0.5”这种情况找出来特别对待。
至于你在“34楼”的公式,请给我一点时间验算。

使用特权

评论回复
46
fushaobing|  楼主 | 2010-10-9 18:16 | 只看该作者
result=60-x*10/y

我觉得这个四舍五入的问题之所以特殊,根本原因在于一个未知的"x*10/y"处于减数的位置。
如果题目改成"result=60+x*10/y"(要求四舍五入),则不会有任何问题。

使用特权

评论回复
47
fushaobing|  楼主 | 2010-10-9 20:11 | 只看该作者
2楼yewuyi方法是可行的,难道LZ的x,y不是整形,如果是整形的话,计算机计算x*100/y是要取整的,
hwwyhy 发表于 2010-10-9 10:24


2楼的方法大多数情况下不会出错,但在某些情况下会出错(比如x=23,y=9)。
我的第一反应就是使用2楼的方法,但是很可惜,不行。
如果2楼的方法可行,就不会有这个帖子出现。

没错,x,y是整型,计算机处理时会取整,会造成数据丢失。所以,我们知道了这一点,就要想办法避免这种数据丢失。这也是这个帖子要解决的问题。

使用特权

评论回复
48
fushaobing|  楼主 | 2010-10-9 20:26 | 只看该作者
to 43楼:
“比如说34.49999999仍然避免不了被判读为34的结果。”

如果result=34.49999999,那么"34"就是我要的结果。这有什么问题吗?四舍五入指的当然是最近的那个小数位了,至于别的位有几个9,是不理睬的。

使用特权

评论回复
49
ZALIN| | 2010-10-9 21:11 | 只看该作者
to fushaobing:
晕,你真的用穷举法验证?我前面已经用数学的方法证明了结果是正确的了

使用特权

评论回复
50
不亦心| | 2010-10-9 21:17 | 只看该作者
LS,我很好奇,你的那个公式是怎么想到的

我数学忒差,要不是你给出推导过程,死活也看不明白

使用特权

评论回复
51
ZALIN| | 2010-10-9 21:26 | 只看该作者
to 50楼:
y是整数时,(y-1)/(2*y)是<0.5的以2*y为模能表达的最大的数

通常所谓的四舍五入是指小数部分>=0.5时向数轴的+无穷大进位,所以如果结果是一个负数,比如-3.5,
四舍五入后应该是-3,而不是-4

使用特权

评论回复
52
不亦心| | 2010-10-9 21:59 | 只看该作者
LZ,俺的那个你不用试了,和2L的根本就没有区别,唯一改变的是把临界点从0.5改成0.4了,晕倒

我都不知道自己怎么想的。。。。

貌似ZALIN的算式可用

使用特权

评论回复
53
johnwjl| | 2010-10-10 10:23 | 只看该作者
确实关乎变量的类型:整型或浮点型,有符号或无符号等。

使用特权

评论回复
54
be1st| | 2010-10-10 12:36 | 只看该作者
这个帖子不错,学习了,更是受教育啊!看来以后要常来了

使用特权

评论回复
55
fushaobing|  楼主 | 2010-10-10 13:03 | 只看该作者
to ZALIN:
我的题目是从一个具体的问题抽象出来的,如果用穷举,是不需要从0x01~0xffffffff全部试完的。我需要验证的范围其实很小。
我准备写一个C程序来穷举。不会太麻烦的。
不是不相信你对公式的解释,老实说,我还是没看懂(汗颜)。不过即使看懂了,我还是会验证一下。做技术的还是谨慎一点的好。

使用特权

评论回复
56
免证入网| | 2010-10-10 13:09 | 只看该作者
result=60-float(x)*10/y;估计很耗时,嘿嘿

使用特权

评论回复
57
fushaobing|  楼主 | 2010-10-10 13:09 | 只看该作者
to 不亦心:
你看懂“ZALIN”的推导过程了吗?哈哈,看来我要努力了。

使用特权

评论回复
58
fushaobing|  楼主 | 2010-10-10 13:26 | 只看该作者
谢谢大家的关注。

有朋友说这个问题必须使用浮点数才能解决。未免有点牵强。
我们总不能为了一个四舍五入的问题,对老板或者客户说,“问题很难办。除非换一个支持浮点数运算的MCU,或者不要求四舍五入的结果是百分百正确。”

使用特权

评论回复
59
fushaobing|  楼主 | 2010-10-10 13:34 | 只看该作者
我是这样解决的。(已经用穷举的方法验证过了)

                if ( (((x*100)%y)==0) && ((((x*100)/y)%10)==5) )
                {
                        //do not round
                        x=x*10/y;
                }
                else
                {
                        // round
                        x=x*100/y;
                        x=(x+5)/10;                        
                }

                if (x<60) result=60-x;
                ...

使用特权

评论回复
60
fushaobing|  楼主 | 2010-10-10 13:40 | 只看该作者
我的想法很简单,把x*10/y的小数部分为“0.5000000000(后面全部是0)”的情况拿出来特别对待。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则