20 个回复
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有啥区别?有没有更好的约法?
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 的大作中提到: 】
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.
: ...................
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.
: ...................
shstone
stone(蓝)
2014-03-20
比如说呢?
【 在 fanci 的大作中提到: 】
: 取决于你的输入是什么类型
: 如果输入是double,那你怎么样也没办法搞对
: 如果输入是字符串,那就有很多办法了
: ...................
shstone
stone(蓝)
2014-03-20
不是啊 我需要的就是一个四舍五入的函数表达,下面的只是一个例子。你这个 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x)已经是形成了的嘛 不需要我在做什么工作了。
【 在 milksea 的大作中提到: 】
: 你确定你想要的不是 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x) 么?
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.
: ...................
milksea
肥了,又肥了 >>>_<<<
2014-03-20
因为浮点数是二进制表示的,所以所谓 1.02 这样的“两位小数”在计算机这种二进制浮点数下是根本不存在的。因此不存在一个 double 到 double 的数学函数能解决这种问题。
所以你还是说清楚到底需要做什么。多数情况舍入只是在 IO 的时候用到,所以就是用 printf、sprintf 就处理了。而如果说在金融计算之类地方,计算过程中需要舍入一定有效位数的,那就不能使用这种二进制浮点数,而要用十进制浮点数、十进制定点数,或者整数处理。
【 在 shstone (stone) 的大作中提到: 】
: 不是啊 我需要的就是一个四舍五入的函数表达,下面的只是一个例子。你这个 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x)已经是形成了的嘛 不需要我在做什么工作了。
timeleap
タイムリープぱらだいす
2014-03-20
应该先明确程序输入数据的取值范围和有效数字位数
【 在 shstone (stone) 的大作中提到: 】
: 不是啊 我需要的就是一个四舍五入的函数表达,下面的只是一个例子。你这个 printf("%.2f", x),或者一般点的 sprintf(s, "%.*f", n, x)已经是形成了的嘛 不需要我在做什么工作了。
shstone
stone(蓝)
2014-03-20
嗯 这个我知道啊,原始需求就是普适性的四舍五入函数,有没有一种法子可以做到?前面说的1.01是理论值,后面的那个1.00是按照我所写函数计算本身所得值的嘛。
【 在 vonNeumann 的大作中提到: 】
: 原始需求是什么?
: 这个需求做不到啊,既然都知道在 double 里面,1.005 和 1.004999****98 是一个东西,那凭啥它保留两位小数就应该按前者得到 1.01 而不是按后者得到 1.00?
cybereagle
2/3的沉默@XMUCSD
2014-03-20
问题是对于1.49999***98它的理论值就是1.00
既然这两者的二进制表示无法区分那么你怎么可能有两个不同的理论值呢
【 在 shstone (stone) 的大作中提到: 】
: 嗯 这个我知道啊,原始需求就是普适性的四舍五入函数,有没有一种法子可以做到?前面说的1.01是理论值,后面的那个1.00是按照我所写函数计算本身所得值的嘛。
shstone
stone(蓝)
2014-03-20
哦,我清楚了了解了 多谢!嘿嘿嘿……
【 在 milksea 的大作中提到: 】
: 因为浮点数是二进制表示的,所以所谓 1.02 这样的“两位小数”在计算机这种二进制浮点数下是根本不存在的。因此不存在一个 double 到 double 的数学函数能解决这种问题。
: 所以你还是说清楚到底需要做什么。多数情况舍入只是在 IO 的时候用到,所以就是用 printf、sprintf 就处理了。而如果说在金融计算之类地方,计算过程中需要舍入一定有效位数的,那就不能使用这种二进制浮点数,而要用十进制浮点数、十进制定点数,或者整数处理。
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.
: ...................
milksea
肥了,又肥了 >>>_<<<
2014-03-20
虽然你已经很努力了,不过这代码还是不靠谱,因为从本质上是没有在小数位上舍入的办法的。即使你在整数位上做舍入,移动小数点后也就自动不精确了。
至于你显示的结果,那是 printf 输出时帮你做的舍入,和你的函数一点关系都没。
【 在 HiGarfield (加菲) 的大作中提到: 】
: #include
: #include
: #include
: ...................
HiGarfield
加菲
2014-03-20
这个我是知道的啊。
浮点机制决定了不可能精确的。
我只是猜测楼主需要完成的功能并实现之。
我并没有说这样的舍入对浮点数是有意义的。
【 在 milksea (肥了,又肥了 >>>_<<
: 虽然你已经很努力了,不过这代码还是不靠谱,因为从本质上是没有在小数位上舍入的办法的。即使你在整数位上做舍入,移动小数点后也就自动不精确了。
: 至于你显示的结果,那是 printf 输出时帮你做的舍入,和你的函数一点关系都没。
milksea
肥了,又肥了 >>>_<<<
2014-03-20
问题你知道你写出来的东西是什么吗?你会把
round_func(1.0048,2)
算出 1.01 来。这种代码乱成一团,结果莫名其妙的东西拿来做什么用?
【 在 HiGarfield (加菲) 的大作中提到: 】
: 这个我是知道的啊。
: 浮点机制决定了不可能精确的。
: 我只是猜测楼主需要完成的功能并实现之。
: ...................
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 来。这种代码乱成一团,结果莫名其妙的东西拿来做什么用?
: ...................
milksea
肥了,又肥了 >>>_<<<
2014-03-20
我只是想告诉你没有意义的事再怎么做也是没有意义的,不是让你锲而不舍战风车。
【 在 HiGarfield (加菲) 的大作中提到: 】
: #include
: #include
: #include
: ...................
fanci
大葡萄
2014-03-20
比如python的decimal类型,可以精确的四舍五入
【 在 shstone () 的大作中提到: 】
: 【 在 fanci 的大作中提到: 】
: 比如说呢?