购物车0种商品
IC邮购网-IC电子元件采购商城
一个四舍五入的问题,大家帮忙看看
(2011/10/16 9:20:00)
求“result=60-x*10/y”的值,x,y是变量。要求四舍五入。
请大家帮忙看看。

网友评论:to LZ:

要想严格使用四舍五入,必须采用浮点运算。

网友评论:
我要求的就是整型。
你的计算看上去很复杂,我不是很明白。写程序时具体如何操作呢?
另外,你在“7楼”的答案不是很简洁吗,为什么现在换了一种计算方式呢?
你可否帮我看看我在17楼的做法是否妥当?
谢谢!

网友评论:
必须严格使用四舍五入。不能使用浮点数(有些MCU不支持浮点数运算,或者考虑到速度、程序空间、省电等因素,尽量避免使用浮点数)。

我在“17楼”写出我的做法。我想知道还有没有更简单的方法。

网友评论:
你不是对7楼表达式的正确性表示怀疑嘛, 我23楼写的就是对7楼表达式的解释

7楼表达式可以分解成
result=60-(x*20+y-1)/(2*y)=60-x*20/(2*y)-(y-1)/(2*y)
其中x*20/(2*y)这项可以表示为a+b/(2*y), 这里的a是结果的整数部分, b是余数
所以上面的表达式可以改写为:
result=60-a-b/(2*y)-(y-1)/(2*y)=60-a-(b+y-1)/(2*y)
最终的结果就是
result=60-a, 当b<=y时, 也就是x*10/y的小数部分<=0.5时, 结果舍入
result=60-a-1, 当b>y时, 也就是x*10/y的小数部分>0.5时, 结果舍去
当然要保证结果的正确性, 中间计算时需要保证不会发生溢出

网友评论:呵呵, result=60-(x*20+y-1)/(2*y)就是LZ需要的严格四舍五入的结果

网友评论:LZ的这个问题本身是个伪命题。

lz要求求result的结果,并对该结果进行四舍五入,那么2楼的解法就是正确解法。

如果需要考虑到所有的整型计算带来的丢位问题,那只有使用浮点,其它都别想了。

另外,你给出的60-23*10/9=34.44444444444444?本身也是伪命题,23*10/9=25.55,因为整型丢位问题,就变成了25,不会自动4舍5入为26的,而你自己在做这个计算时候,却把它幻化成了26,结果自然就不对,正确应该是60-25=35,而并不是你所理解的34。
而你在求600-23*100/9的时候又进行了取整做减法,所以,问题是你自己两者计算条件不对等造成的。

网友评论:搅一下浑水,俺也来一个:
result=600-x*100/y;
result=(result+6)/10;

2L之所以被LZ抓到bug,无非是LZ没有说明是最终结果四舍五入,而中间计算过程要保留浮点数,这样一来,2L的公式就没有处理0.5这个零界值的问题
所以只要解决后面计算过程五舍六入,即可保证整体结果四舍五入。。。。。
麻烦LZ也帮俺验证一下这个公式,是不是也有虫子....

网友评论:
搅一下浑水,俺也来一个:
result=600-x*100/y;
result=(result+6)/10;

2L之所以被LZ抓到bug,无非是LZ没有说明是最终结果四舍五入,而中间计算过程要保留浮点数,这样一来,2L的公式就没有处理0.5这个零界值的问题 ...
不亦心 发表于 2010-10-9 08:44
只要按照LZ那种互相矛盾的算法,这也是不成立的。

例如:x=496,y=100,则即不成立。

网友评论:

更正32L

result=(x*100/y+6)/10;
result=60-result;
貌似这样就可以了
先把后面的五舍六入,再作减法,才能保证整体结果四舍五入

网友评论:
更正32L

result=(x*100/y+6)/10;
result=60-result;
貌似这样就可以了
先把后面的五舍六入,再作减法,才能保证整体结果四舍五入
不亦心 发表于 2010-10-9 09:09
还是不成立,具体就不说了。

网友评论:四舍五入應該是逢五進1吧

网友评论:2楼yewuyi方法是可行的,难道LZ的x,y不是整形,如果是整形的话,计算机计算x*100/y是要取整的,

网友评论:
to yewuyi:
谢谢你关注这个帖子。
我发这个帖子是想和大家讨论技术问题。请不要再用“见鬼了”,“LZ脑子犯晕了”这样的字眼。
尊重别人即是尊重自己。 ...
fushaobing 发表于 2010-10-8 17:58
你竟然能和‘尊重别人即是尊重自己’结合起来,I 服了 you !

没有自尊心是不对的,过于强烈的自尊心只会导致自己经常急火攻心。

网友评论:这种帖子好

网友评论:二位,蛋定...啊,

网友评论:
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

网友评论:恩,是的,这就要求一个精度了,精度越高如果不用浮点的话,计算量就要越大

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

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

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

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

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

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

网友评论:result=60-x*10/y

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

网友评论:
2楼yewuyi方法是可行的,难道LZ的x,y不是整形,如果是整形的话,计算机计算x*100/y是要取整的,
hwwyhy 发表于 2010-10-9 10:24
2楼的方法大多数情况下不会出错,但在某些情况下会出错(比如x=23,y=9)。
我的第一反应就是使用2楼的方法,但是很可惜,不行。
如果2楼的方法可行,就不会有这个帖子出现。

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

网友评论:
“比如说34.49999999仍然避免不了被判读为34的结果。”

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

网友评论:to fushaobing:
晕,你真的用穷举法验证?我前面已经用数学的方法证明了结果是正确的了

网友评论:LS,我很好奇,你的那个公式是怎么想到的

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

网友评论:
y是整数时,(y-1)/(2*y)是<0.5的以2*y为模能表达的最大的数

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

网友评论:LZ,俺的那个你不用试了,和2L的根本就没有区别,唯一改变的是把临界点从0.5改成0.4了,晕倒

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

貌似ZALIN的算式可用

网友评论:确实关乎变量的类型:整型或浮点型,有符号或无符号等。

网友评论:这个帖子不错,学习了,更是受教育啊!看来以后要常来了

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

网友评论:result=60-float(x)*10/y;估计很耗时,嘿嘿

网友评论:to 不亦心:
你看懂“ZALIN”的推导过程了吗?哈哈,看来我要努力了。

网友评论:谢谢大家的关注。

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

网友评论:我是这样解决的。(已经用穷举的方法验证过了)

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;
...

网友评论:我的想法很简单,把x*10/y的小数部分为“0.5000000000(后面全部是0)”的情况拿出来特别对待。

网友评论:ZALIN的算法,应该是对整数除法运算中取整误差的一种修正方法,用修正一个 (y-1)/2*y(小于0.5的一个最大值)的小数部分,使舍去的小数部分大于等于0.5的自动进位为1。
不知道自己的想法是不是正确的?

网友评论:你简直就是一个SB...


滚你妈蛋..

网友评论:to ZALIN:
你的公式是准确的!
我已经用穷举的方法试过了,我需要的约两万组数据全部能得出准确结果。
谢谢你!

网友评论:to ZALIN:
你的公式是正确的!
我已经用穷举的方法试过了。我需要的约两万种情况全部能得出正确结果。
谢谢你!

网友评论:
你简直就是一个SB...


滚你妈蛋..
yewuyi 发表于 2010-10-10 16:50
急火攻心了?
此时此刻,你做人的水准和做事的水准我已经知道了。

本来,热爱技术的人在一起讨论技术问题是一件很开心的事。懂与不懂,错与对又有什么关系?大家讨论分析一下,总会明白的。何必三番两次出言不逊,现在连脏话都骂出来了?

虽然是在网络上,但人与人之间的尊重跟在现实生活中没有区别。

网友评论:
急火攻心了?
此时此刻,你做人的水准和做事的水准我已经知道了。

本来,热爱技术的人在一起讨论技术问题是一件很开心的事。懂与不懂,错与对又有什么关系?大家讨论分析一下,总会明白的。何必三番两次出言不逊 ...
fushaobing 发表于 2010-10-11 13:44
是你这SB先骂老子的。

只要不是SB都应该知道‘见鬼了’,‘犯晕了’基本是一些中性词语。

网友评论:像你这么嚣张的俺见多了,别以为俺不会开口骂人。。。

网友评论:俺好心给你回答问题,你TMD不感谢半句,反而攻击老子,你以为俺欺负是吧。。。


你5楼的计算本来是就矛盾的,我在随后的帖子中已经分析的清清楚楚,你自己没本事把问题描述清楚,关别人屁事情。

网友评论:总结(结贴)

题目:求“result=60-x*10/y”的值,要求四舍五入。所有变量都为长整型。(不可以使用浮点运算)


7楼给出的答案“result=60-(x*20+y-1)/(2*y)”能得到百分百正确的结果,而且非常简洁。
谢谢“ZALIN”!

我自己的做法如下。


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

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

虽然可行,但过于繁琐。

谢谢所有关注或回复此贴的人!谢谢你们的意见!

此贴对任何人引起的任何不快,我在这里表示歉意。那并不是我想看到的。

2010-10-11

网友评论:路过,学习了。

网友评论:我完整的看了所有的评论,其实是LZ和2楼对问题的理解有偏差,原因32楼已经说了
这里对2楼的算法做一下改进就行了,如下:
result =( (600*y-x*100)/y + 5)/10
应该说两位高手说的都没错!
再强调一下2楼的算法对解四舍五入没有问题

网友评论:

70楼是错误的

网友评论:
谢谢你的耐心和指教!
我验算了你的公式,全部能得出正确结果。可否请教一下你的思路?为什么你那样一改,就ok了?

另外,当客户将公式“result=60-x*10/y”(要求四舍五入)提供给我之后,他将怎样验收我的软件呢?他不外乎就是通过Windows系统附件里面的“计算器”,或者用Excel制作一个表格来验算。客户不管计算过程,只要正确结果。
因此,对于本贴的问题,2楼的算法达不到要求(大部分正确,小部分不正确)。我这样说,不知道您是否认同?

网友评论:
补充一点。
你说“再强调一下2楼的算法对解四舍五入没有问题”,我有不同的意见。我的看法是,如果“x*10/y”前面是一个加号,那么2楼的算法完全正确。如果“x*10/y”前面是一个减号(即为负数),则不可以这样处理。
你怎么看?想听听您的意见。

网友评论:

哈哈,有趣
我验算了一下
基本正确

网友评论:2楼的做法是对(10*x/y)这个项做了四舍五入,而我的做法是对(60-10*x/y)做四舍五入,这就是根本的区别。所以我说2楼关于四舍五入的算法是没错的。
另外这所以会有10*x/y前面是+运算可以,对-运算就不成立,是因为C语言对整形数的运算规则里小数点后面都是舍去的。所以(10*x/y)这项整形计算值<用浮点型运算值
另外我对7楼的算法也很感兴趣,试图去证明它的正确性,(y-1/2y)<0.5,最接近0.5的有效表达值这是成立的。
共同研究,呵呵。也请原创作者证明一下,好比说用数学归纳法。穷举不是个科学的验证方法

网友评论:楼主你可以把问题看成是(60-(xx.000(纯整数)+0.xxx(纯小数)))这样你就明白为什么前面是+就行是-就有可能出错

网友评论:
关于(y-1)/2y<0.5并且最接近0.5,因为y/2y=0.5,而y-1是小于y的最大整数,显而易见可以得出前述结论

你在72楼的算式是把LZ的算式转换成了一个‘正’表达式,所以可以适用+0.5再取整的方法,
不过可以简化成:result =(60*y-x*10+y/2)/y,60*y>=x*10

我们可以归纳出普遍的整数运算的四舍五入的方法:
形如:result=a+b/c,四舍五入可以表示为:result=a+(b+c/2)/c
形如:result=a-b/c,四舍五入可以表示为:result=a-(2b+c-1)/2c 或result=a-(b+(c-1)/2)/c
上述算式中的除法是整数运算,也就是取整数,丢弃余数。

如果一个算式中有多于一个的除法表达式,可以合并成一个除法表达式后再使用上述方法

网友评论:to 雨下枫:
谢谢你的解释!
感觉很不可思议!我为什么就想不到呢?哈哈。
7楼后来也给出了推导过程,麻烦你自己找一下。

另外,我觉得对(10*x/y)这个项做四舍五入应该这样写:result=60-(x*20+y)/(2*y).
这与2楼的“result =( 600-x*100/y + 5)/10”还是有很大区别的。我刚才验算了约两万组数据,前者产生18个错误,后者产生457个错误。

网友评论:to ZALIN
可能我没表达清楚,我是想证明为什么对任意x/y(x,y为整数),做四舍五入可以用(2x+y-1)/2y来解决呢?
想通过数学的方法去证明它

网友评论:不好意思打扰了,我看明白了

网友评论:to ZALIN:
你归纳得很精彩!佩服!
谢谢你!

网友评论:如果运算的数字不是太大的话,用10楼的方法
尽量把数放大,别超出范围就行。

网友评论:ws

网友评论:该觉楼主的命题有问题:
1.x,y,result的数据类型没有交代;
2.四舍五入是针对哪一位,没有交代;

浏览:(1343)| 评论( 0 )
博文评论

  • 昵 称:
  • 内 容:10~250个字符
  • 验证码: 验证码看不清楚?请点击刷新验证码
  •                      
  • 博文分类

    热点博文

    最新博文

    最新评论

    IC电子元件查询
    IC邮购网电子元件品质保障