打印

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

[复制链接]
楼主: fushaobing
手机看帖
扫描二维码
随时随地手机跟帖
21
HWM| | 2010-10-8 20:53 | 只看该作者 回帖奖励 |倒序浏览
四舍五入,加0.5然后取整(通常直接赋值给整型变量)即可。

result=60-x*10/y + 0.5;

二楼没有注意result是整型,计算赋值后会引入误差。

使用特权

评论回复
22
le062| | 2010-10-8 21:09 | 只看该作者
编程将一个浮点数四舍五入到小数的第N位,N由scanf输入

double a=0.123556;
int n = 3;
// N由scanf输入
a = (double) ( (int) (a * pow(10,n) + 0.5)) / pow(10,n);
printf("%lf",a);


二楼就是这个算法吧。很强大

使用特权

评论回复
23
ZALIN| | 2010-10-8 21:49 | 只看该作者
to 13楼:
设20*x=a*2*y+b, 其中b<2*y
result=60-(x*20+y-1)/(2*y)=60-a-(b+y-1)/(2*y)
result=60-a, 当b<=y时
result=60-a-1, 当b>y时
这里假设LZ要求的是整数运算

如果使用浮点计算, 由于尾数的精度问题, +0.5的方法也不是百分百正确的

使用特权

评论回复
24
fushaobing|  楼主 | 2010-10-8 22:35 | 只看该作者
谢谢大家的回复。

我补充一下参数的类型。如下:
unsigned long int result;
unsigned long int x;
unsigned long int y;

(不可以使用浮点计算)

使用特权

评论回复
25
fushaobing|  楼主 | 2010-10-8 22:52 | 只看该作者
“比如x=23,y=9.
60-23*10/9=34.44444444444444,四舍五入后的结果是34.”

不好意思,可能是我表达不够清楚。上面的计算并不是MCU的计算过程,而是我在草稿纸上的一个验算过程。
另外,x,y都是unsigned long int型。

使用特权

评论回复
26
HWM| | 2010-10-8 22:55 | 只看该作者
to LZ:

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

使用特权

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

使用特权

评论回复
28
fushaobing|  楼主 | 2010-10-8 23:26 | 只看该作者
to 26楼:
必须严格使用四舍五入。不能使用浮点数(有些MCU不支持浮点数运算,或者考虑到速度、程序空间、省电等因素,尽量避免使用浮点数)。

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

使用特权

评论回复
29
ZALIN| | 2010-10-8 23:43 | 只看该作者
to 27楼:
你不是对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时, 结果舍去
当然要保证结果的正确性, 中间计算时需要保证不会发生溢出

使用特权

评论回复
30
ZALIN| | 2010-10-8 23:52 | 只看该作者
呵呵, result=60-(x*20+y-1)/(2*y)就是LZ需要的严格四舍五入的结果

使用特权

评论回复
31
yewuyi| | 2010-10-9 08:43 | 只看该作者
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的时候又进行了取整做减法,所以,问题是你自己两者计算条件不对等造成的。

使用特权

评论回复
32
不亦心| | 2010-10-9 08:44 | 只看该作者
搅一下浑水,俺也来一个:
result=600-x*100/y;
result=(result+6)/10;

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

使用特权

评论回复
33
yewuyi| | 2010-10-9 08:55 | 只看该作者
搅一下浑水,俺也来一个:
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,则即不成立。

使用特权

评论回复
34
不亦心| | 2010-10-9 09:09 | 只看该作者
本帖最后由 不亦心 于 2010-10-9 09:10 编辑

更正32L

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

使用特权

评论回复
35
yewuyi| | 2010-10-9 09:35 | 只看该作者
更正32L

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


还是不成立,具体就不说了。

使用特权

评论回复
36
LKC134| | 2010-10-9 09:38 | 只看该作者
四舍五入應該是逢五進1吧

使用特权

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

使用特权

评论回复
38
yewuyi| | 2010-10-9 10:38 | 只看该作者
to yewuyi:
谢谢你关注这个帖子。
我发这个帖子是想和大家讨论技术问题。请不要再用“见鬼了”,“LZ脑子犯晕了”这样的字眼。
尊重别人即是尊重自己。 ...
fushaobing 发表于 2010-10-8 17:58


你竟然能和‘尊重别人即是尊重自己’结合起来,I 服了 you !

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

使用特权

评论回复
39
datouyuan| | 2010-10-9 10:43 | 只看该作者
这种帖子好

使用特权

评论回复
40
hwwyhy| | 2010-10-9 10:43 | 只看该作者
二位,蛋定...啊,:)

使用特权

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

本版积分规则