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

[复制链接]
14421|88
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
hwwyhy 发表于 2010-10-9 10:48 | 显示全部楼层
恩,是的,这就要求一个精度了,精度越高如果不用浮点的话,计算量就要越大
bald 发表于 2010-10-9 11:44 | 显示全部楼层
这是一个复合运算的误差传递问题。
无论采用什么算法,只要中间过程有舍有入,其运算结果的最后一位必然都是可疑的。
采用半进位方法提高运算精度,一般只针对单一运算。
有一个办法可以提高复合运算的精度,就是将所有的源数据都乘以适当的倍数,最后的运算结果做除以相同的因子后做取舍,不过这也仅是0.51、0.501、0.500。。。001之间的区别。比如说34.49999999仍然避免不了被判读为34的结果。因此这种方法只是减小了判别出错的几率,可是相应的代价也是相当大的。
 楼主| 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楼给出了我的做法。只是我觉得这个问题有点意思,所以拿出来和大家讨论一下。

老实说,对于说话不经过大脑,却三番两次口出不逊的人,我的自尊心真的受到了伤害。
 楼主| fushaobing 发表于 2010-10-9 18:04 | 显示全部楼层
to ZALIN:
谢谢你的解释。
我会用穷举的方法验证你在“7楼”给出的公式。但我的水平有限,需要一点时间。

to 32楼:
谢谢你。你说到问题的点子上了。我在17楼的处理就是专门把“0.5”这种情况找出来特别对待。
至于你在“34楼”的公式,请给我一点时间验算。
 楼主| fushaobing 发表于 2010-10-9 18:16 | 显示全部楼层
result=60-x*10/y

我觉得这个四舍五入的问题之所以特殊,根本原因在于一个未知的"x*10/y"处于减数的位置。
如果题目改成"result=60+x*10/y"(要求四舍五入),则不会有任何问题。
 楼主| 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是整型,计算机处理时会取整,会造成数据丢失。所以,我们知道了这一点,就要想办法避免这种数据丢失。这也是这个帖子要解决的问题。
 楼主| fushaobing 发表于 2010-10-9 20:26 | 显示全部楼层
to 43楼:
“比如说34.49999999仍然避免不了被判读为34的结果。”

如果result=34.49999999,那么"34"就是我要的结果。这有什么问题吗?四舍五入指的当然是最近的那个小数位了,至于别的位有几个9,是不理睬的。
ZALIN 发表于 2010-10-9 21:11 | 显示全部楼层
to fushaobing:
晕,你真的用穷举法验证?我前面已经用数学的方法证明了结果是正确的了
不亦心 发表于 2010-10-9 21:17 | 显示全部楼层
LS,我很好奇,你的那个公式是怎么想到的

我数学忒差,要不是你给出推导过程,死活也看不明白
ZALIN 发表于 2010-10-9 21:26 | 显示全部楼层
to 50楼:
y是整数时,(y-1)/(2*y)是<0.5的以2*y为模能表达的最大的数

通常所谓的四舍五入是指小数部分>=0.5时向数轴的+无穷大进位,所以如果结果是一个负数,比如-3.5,
四舍五入后应该是-3,而不是-4
不亦心 发表于 2010-10-9 21:59 | 显示全部楼层
LZ,俺的那个你不用试了,和2L的根本就没有区别,唯一改变的是把临界点从0.5改成0.4了,晕倒

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

貌似ZALIN的算式可用
johnwjl 发表于 2010-10-10 10:23 | 显示全部楼层
确实关乎变量的类型:整型或浮点型,有符号或无符号等。
be1st 发表于 2010-10-10 12:36 | 显示全部楼层
这个帖子不错,学习了,更是受教育啊!看来以后要常来了
 楼主| fushaobing 发表于 2010-10-10 13:03 | 显示全部楼层
to ZALIN:
我的题目是从一个具体的问题抽象出来的,如果用穷举,是不需要从0x01~0xffffffff全部试完的。我需要验证的范围其实很小。
我准备写一个C程序来穷举。不会太麻烦的。
不是不相信你对公式的解释,老实说,我还是没看懂(汗颜)。不过即使看懂了,我还是会验证一下。做技术的还是谨慎一点的好。
免证入网 发表于 2010-10-10 13:09 | 显示全部楼层
result=60-float(x)*10/y;估计很耗时,嘿嘿
 楼主| fushaobing 发表于 2010-10-10 13:09 | 显示全部楼层
to 不亦心:
你看懂“ZALIN”的推导过程了吗?哈哈,看来我要努力了。
 楼主| fushaobing 发表于 2010-10-10 13:26 | 显示全部楼层
谢谢大家的关注。

有朋友说这个问题必须使用浮点数才能解决。未免有点牵强。
我们总不能为了一个四舍五入的问题,对老板或者客户说,“问题很难办。除非换一个支持浮点数运算的MCU,或者不要求四舍五入的结果是百分百正确。”
 楼主| 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;
                ...
 楼主| fushaobing 发表于 2010-10-10 13:40 | 显示全部楼层
我的想法很简单,把x*10/y的小数部分为“0.5000000000(后面全部是0)”的情况拿出来特别对待。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部