c语言中四舍五入的表达式,[求助][讨论]C语言中四舍五入的函数

博客讨论了在编程中遇到浮点数四舍五入的问题,由于二进制浮点数表示的局限性,1.005在计算机中无法精确表示,导致四舍五入函数的实现出现误差。讨论了不同的处理方法,包括使用printf/sprintf进行输出时的自动舍入,以及Python的decimal类型的精确四舍五入。同时指出,对于需要高精度计算的情况,应考虑使用专门的数据类型或算法。
摘要由CSDN通过智能技术生成

20 个回复

a582bcbada2697988ab88bb6a55895f3.png

fanci

大葡萄

2014-03-20

取决于你的输入是什么类型

如果输入是double,那你怎么样也没办法搞对

如果输入是字符串,那就有很多办法了

【 在 shstone () 的大作中提到: 】

: 我在写一个四舍五入的round( r, n ) 函数,我所写的 floor( r*10^n + 0.5 ) / 10^n这一句感觉有错误,有些数据是达不到的比如round(1.005, 2)=1.01。但是,1.005不能用double精确表示,它的表示约为1.0049999999999998。因此,以上代码计算的“r*10^2 + 0.5”约等于100.999999999998,取整后为100结果,其代码给出的答案是1.00,错了。但是不知道怎么修正,与(int)(r^n + 0.5)/10^n有啥区别?有没有更好的约法?

a582bcbada2697988ab88bb6a55895f3.png

itx

itx

2014-03-20

如果数据来源是有理数,感觉可以用分数来做

如果已知数据小数点后位数,那么也可以转化成分数

举例:假设已知1.005有3位小数,那么乘以1000,得1004.999999999998,离的最近的整数是1005,因此可知原数是1.005,可写成1005/1000,再加上1/200,得1010/1000,因此四舍五入后得1.01

如果小数点后位数很多,上述方法就不准

我在写一个四舍五入的round( r, n ) 函数,我所写的 floor( r*10^n + 0.5 ) / 10^n这一句感觉有错误,有些数据是达不到的比如round(1.005, 2)=1.01。但是,1.005不能用double精确表示,它的表示约为1.0049999999999998。因此,以上代码计算的“r*10^2 + 0.5”约等于100.999999999998,取整后为100结果,其代码给出的答案是1.00,错了。但是不知道怎么修正,与(int)(r^n + 0.5)/10^n有啥区别?有没有更好的约法?

【 在 shstone 的大作中提到: 】

a582bcbada2697988ab88bb6a55895f3.png

milksea

肥了,又肥了 >>>_<<<

2014-03-20

你确定你想要的不是 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x) 么?

【 在 shstone (stone) 的大作中提到: 】

: 我在写一个四舍五入的round( r, n ) 函数,我所写的 floor( r*10^n + 0.5 ) / 10^n这一句感觉有错误,有些数据是达不到的比如round(1.005, 2)=1.01。但是,1.005不能用double精确表示,它的表示约为1.0049999999999998。因此,以上代码计算的“r*10^2 + 0.5”约等于100.

: ...................

a582bcbada2697988ab88bb6a55895f3.png

HiGarfield

加菲

2014-03-20

如果你的输入是double的1.0049999999999998,那么给出的结果为1.00是正确的。

1.5只是你的预想输入,实际输入不是1.5。

你这种需求,可以试试,先按照3位四舍五入,其结果再按照2位四舍五入。

【 在 shstone (stone) 的大作中提到: 】

: 我在写一个四舍五入的round( r, n ) 函数,我所写的 floor( r*10^n + 0.5 ) / 10^n这一句感觉有错误,有些数据是达不到的比如round(1.005, 2)=1.01。但是,1.005不能用double精确表示,它的表示约为1.0049999999999998。因此,以上代码计算的“r*10^2 + 0.5”约等于100.

: ...................

a582bcbada2697988ab88bb6a55895f3.png

shstone

stone(蓝)

2014-03-20

比如说呢?

【 在 fanci 的大作中提到: 】

: 取决于你的输入是什么类型

: 如果输入是double,那你怎么样也没办法搞对

: 如果输入是字符串,那就有很多办法了

: ...................

a582bcbada2697988ab88bb6a55895f3.png

shstone

stone(蓝)

2014-03-20

不是啊  我需要的就是一个四舍五入的函数表达,下面的只是一个例子。你这个 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x)已经是形成了的嘛  不需要我在做什么工作了。

【 在 milksea 的大作中提到: 】

: 你确定你想要的不是 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x) 么?

a582bcbada2697988ab88bb6a55895f3.png

vonNeumann

劣币驱逐良币 | 少灌水

2014-03-20

原始需求是什么?

这个需求做不到啊,既然都知道在 double 里面,1.005 和 1.004999****98 是一个东西,那凭啥它保留两位小数就应该按前者得到 1.01 而不是按后者得到 1.00?

【 在 shstone (stone) 的大作中提到: 】

: 我在写一个四舍五入的round( r, n ) 函数,我所写的 floor( r*10^n + 0.5 ) / 10^n这一句感觉有错误,有些数据是达不到的比如round(1.005, 2)=1.01。但是,1.005不能用double精确表示,它的表示约为1.0049999999999998。因此,以上代码计算的“r*10^2 + 0.5”约等于100.

: ...................

a582bcbada2697988ab88bb6a55895f3.png

milksea

肥了,又肥了 >>>_<<<

2014-03-20

因为浮点数是二进制表示的,所以所谓 1.02 这样的“两位小数”在计算机这种二进制浮点数下是根本不存在的。因此不存在一个 double 到 double 的数学函数能解决这种问题。

所以你还是说清楚到底需要做什么。多数情况舍入只是在 IO 的时候用到,所以就是用 printf、sprintf 就处理了。而如果说在金融计算之类地方,计算过程中需要舍入一定有效位数的,那就不能使用这种二进制浮点数,而要用十进制浮点数、十进制定点数,或者整数处理。

【 在 shstone (stone) 的大作中提到: 】

: 不是啊  我需要的就是一个四舍五入的函数表达,下面的只是一个例子。你这个 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x)已经是形成了的嘛  不需要我在做什么工作了。

a582bcbada2697988ab88bb6a55895f3.png

timeleap

タイムリープぱらだいす

2014-03-20

应该先明确程序输入数据的取值范围和有效数字位数

【 在 shstone (stone) 的大作中提到: 】

: 不是啊  我需要的就是一个四舍五入的函数表达,下面的只是一个例子。你这个 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x)已经是形成了的嘛  不需要我在做什么工作了。

a582bcbada2697988ab88bb6a55895f3.png

shstone

stone(蓝)

2014-03-20

嗯  这个我知道啊,原始需求就是普适性的四舍五入函数,有没有一种法子可以做到?前面说的1.01是理论值,后面的那个1.00是按照我所写函数计算本身所得值的嘛。

【 在 vonNeumann 的大作中提到: 】

: 原始需求是什么?

: 这个需求做不到啊,既然都知道在 double 里面,1.005 和 1.004999****98 是一个东西,那凭啥它保留两位小数就应该按前者得到 1.01 而不是按后者得到 1.00?

17e95632f5f1ebc0dd505946f7f87edb.png

cybereagle

2/3的沉默@XMUCSD

2014-03-20

问题是对于1.49999***98它的理论值就是1.00

既然这两者的二进制表示无法区分那么你怎么可能有两个不同的理论值呢

【 在 shstone (stone) 的大作中提到: 】

: 嗯  这个我知道啊,原始需求就是普适性的四舍五入函数,有没有一种法子可以做到?前面说的1.01是理论值,后面的那个1.00是按照我所写函数计算本身所得值的嘛。

a582bcbada2697988ab88bb6a55895f3.png

shstone

stone(蓝)

2014-03-20

哦,我清楚了了解了  多谢!嘿嘿嘿……

【 在 milksea 的大作中提到: 】

: 因为浮点数是二进制表示的,所以所谓 1.02 这样的“两位小数”在计算机这种二进制浮点数下是根本不存在的。因此不存在一个 double 到 double 的数学函数能解决这种问题。

: 所以你还是说清楚到底需要做什么。多数情况舍入只是在 IO 的时候用到,所以就是用 printf、sprintf 就处理了。而如果说在金融计算之类地方,计算过程中需要舍入一定有效位数的,那就不能使用这种二进制浮点数,而要用十进制浮点数、十进制定点数,或者整数处理。

a582bcbada2697988ab88bb6a55895f3.png

HiGarfield

加菲

2014-03-20

#include 

#include 

#include 

double round_func(double r, int n){

return (double)((int)((double)((int)(r*pow(10.0,(double)(n+1))+0.5))/10.0+0.5))/pow(10.0,(double)n);

}

main(){

clrscr();

printf("%g\n",round_func(1.0049999999999998,2));

getch();

}

你看看这个是不是你要的功能。

【 在 shstone (stone) 的大作中提到: 】

: 我在写一个四舍五入的round( r, n ) 函数,我所写的 floor( r*10^n + 0.5 ) / 10^n这一句感觉有错误,有些数据是达不到的比如round(1.005, 2)=1.01。但是,1.005不能用double精确表示,它的表示约为1.0049999999999998。因此,以上代码计算的“r*10^2 + 0.5”约等于100.

: ...................

a582bcbada2697988ab88bb6a55895f3.png

milksea

肥了,又肥了 >>>_<<<

2014-03-20

虽然你已经很努力了,不过这代码还是不靠谱,因为从本质上是没有在小数位上舍入的办法的。即使你在整数位上做舍入,移动小数点后也就自动不精确了。

至于你显示的结果,那是 printf 输出时帮你做的舍入,和你的函数一点关系都没。

【 在 HiGarfield (加菲) 的大作中提到: 】

: #include 

: #include 

: #include 

: ...................

a582bcbada2697988ab88bb6a55895f3.png

HiGarfield

加菲

2014-03-20

这个我是知道的啊。

浮点机制决定了不可能精确的。

我只是猜测楼主需要完成的功能并实现之。

我并没有说这样的舍入对浮点数是有意义的。

【 在 milksea (肥了,又肥了 >>>_<<

: 虽然你已经很努力了,不过这代码还是不靠谱,因为从本质上是没有在小数位上舍入的办法的。即使你在整数位上做舍入,移动小数点后也就自动不精确了。

: 至于你显示的结果,那是 printf 输出时帮你做的舍入,和你的函数一点关系都没。

a582bcbada2697988ab88bb6a55895f3.png

milksea

肥了,又肥了 >>>_<<<

2014-03-20

问题你知道你写出来的东西是什么吗?你会把

round_func(1.0048,2)

算出 1.01 来。这种代码乱成一团,结果莫名其妙的东西拿来做什么用?

【 在 HiGarfield (加菲) 的大作中提到: 】

: 这个我是知道的啊。

: 浮点机制决定了不可能精确的。

: 我只是猜测楼主需要完成的功能并实现之。

: ...................

a582bcbada2697988ab88bb6a55895f3.png

HiGarfield

加菲

2014-03-20

#include

#include

#include

#include

double round_func(double r,int n){

return ((int)((r+DBL_EPSILON)*pow(10,(double)n)+0.5))/pow(10,(double)n);

}

main(){

clrscr();

printf("%.2f\n",round_func(1.0049999999999998,2));

getch();

}

【 在 milksea (肥了,又肥了 >>>_<<

: 问题你知道你写出来的东西是什么吗?你会把

:   round_func(1.0048,2)

: 算出 1.01 来。这种代码乱成一团,结果莫名其妙的东西拿来做什么用?

: ...................

a582bcbada2697988ab88bb6a55895f3.png

milksea

肥了,又肥了 >>>_<<<

2014-03-20

我只是想告诉你没有意义的事再怎么做也是没有意义的,不是让你锲而不舍战风车。

【 在 HiGarfield (加菲) 的大作中提到: 】

: #include

: #include

: #include

: ...................

a582bcbada2697988ab88bb6a55895f3.png

fanci

大葡萄

2014-03-20

比如python的decimal类型,可以精确的四舍五入

【 在 shstone () 的大作中提到: 】

: 【 在 fanci 的大作中提到: 】

: 比如说呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值