• 全部
  • VC综合技术
  • 互联网技术
  • MFC AppLauncher
  • .NET 技术
  • 界面
  • 进程
  • 算法
  • 硬件/系统
  • 数据库
  • VC++技术资源

怎么这么简单的三行代码竟然也运算错了??关于四舍五入的

mybios 2004-11-01 09:27:09
float round(float v , float n)
{
float temp;
temp = pow( 10 , n);
float f = (int)(v * temp + 0.5) / temp;//监视这个表达式没错
return f;//运行到这里f就变了。好像没有四舍五入的样子
}
这个函数的作用是把v的浮点数只保留n位小数的四舍五入算法。再watch里面运行到float f = (int)(v * temp + 0.5) / temp;的时候,我监视了(int)(v * temp + 0.5) / temp表达式的值,这时没有错,但是赋值到f后,再监视f的值就错了,好像没有四舍五入的样子
...全文
253 点赞 收藏 29
写回复
29 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
mybios 2004-11-02
的确是这样,就是这个float的误差,最后我还是用了自己的算法,这样算来算去都没有错。syson(Syson) 的算法我还没有试。
double round(double v , double n)
{
double temp = pow(10 , n);
return (int)(v*temp+0.511111111111f)/temp;
}
谢谢大家了。散分
回复
mybios 2004-11-02
to:LittleLee(飞天猫)
对于您写的函数,我作个分析看看,如果用round(0.45 , 1)调用,则
float round(float v , float n)
{
float temp;
temp = pow( 10 , n); //temp 的结果会是 10的n次方 = 10
CString l_str;
l_str.Format("%.0f",temp); //Format,并且不取小数,l_str得出结果是"10"
float f=atof(l_str); //atof把l_str转换成double型,则f结果是10.00000

return f //然后把f返回,即返回10,有何意义?而且,这句好像漏了个“;”吧?
}

以上是我的分析结果。但我没有拿到vc调试器里运行。小弟不才,如有不对,请多多指出。谢谢。
回复
syl5005 2004-11-02
学习呀
回复
I_Love_CPP 2004-11-02
帮你查到了,汗。。。。

C语言编程中,有时需要把float转换成int数值使用;但在VC++中,这种转换有时会出现大的误差。例如:float ftemp = 1140.00; int itemp = (int)ftemp;此时itemp的值为1139,误差为1----这就是业界成为的“1误差”(汗。。。,以前都不知道)。很多种类型转换都存在1误差(我就不一一写了)。
防范1误差的方法:
1、将变量在类中定义;
2、在适当的时候把1误差补上(加减1)。
回复
float精度问题,最好用整型计算
回复
LittleLee 2004-11-02
可能是我没看清你的意思,我写的函数是把小数位去掉!
回复
danielzhu 2004-11-02
UP
回复
看来我还很菜 想楼主学习:)

打发点分给我吧 ^-^
回复
想了很久,终于想起是什么问题了。但是不确定是不是这样。我记得当年看过一篇文章,说C++对float和double的处理的问题,会自动转换成double,而在double型里,如果传入的是4.5,则会自动转换成4.4999999999998……

我怎么不知道?
晕了

回复
syson 2004-11-02
float round(double v , float n)
{
double temp;
temp = pow( 10 , n);
float f = (int)((float)(v * temp) + 0.5) / temp
return f;
}
我的机这样可以了。楼主试试。
将v和temp换成double,然后相乘后再强制转为float,那就可以了。
问题主要出自相乘之后的精度问题。
回复
LittleLee 2004-11-01
int和float之间强制转换就是有问题
我说一个方法可能麻烦一点但应该能解决问题

float round(float v , float n)
{
float temp;
temp = pow( 10 , n);
CString l_str;
l_str.Format("%.0f",temp);
float f=atof(l_str);

return f
}
回复
mybios 2004-11-01
忘记去掉了个float了。再改一点
double round(double v , double n)
{
double temp = pow(10 , n);
return (int)(v*temp+0.511111111111f)/temp;
}
回复
mybios 2004-11-01
想了很久,终于想起是什么问题了。但是不确定是不是这样。我记得当年看过一篇文章,说C++对float和double的处理的问题,会自动转换成double,而在double型里,如果传入的是4.5,则会自动转换成4.4999999999998,这个4.4999999999998 + 0.5,结果还是4.9999999999998,强制转换成int后,还是会变成4!解决办法是
double round(double v , double n)
{
float temp = (float)pow(10 , n);
return (int)(v*temp+0.511111111111f)/temp; // 加了很多1进去,呵呵,问题就解决了
}
回复
mybios 2004-11-01
你们试试用round(0.45 , 1)
结果应该会错!会变成0.4
回复
syson 2004-11-01
问题出现在浮点数的精度上。其实2.5+0.5有可能小于3.000000000,所以出现这个问题。
试试用双精度,然后2.5+0.5000..01可以解决。但也有危险……
-_-!
回复
joysunstar 2004-11-01
我按照你的程序作了,但是没有出现你说的结果,你可能传入的参数小数位太多了吧
float型最多7位有效数字
回复
vioy 2004-11-01
原因在于FLOAT型的数据精度问题,
楼主是要temp的四舍五入结果 还是 temp除temp 的四舍五入结果?
回复
暗黑帝国 2004-11-01
#include <stdio.h>
#include <math.h>

float round(float v , float n)
{
float temp;
temp = pow( 10 , n);
return ((int)(v * temp + 0.5) / temp);//¼àÊÓÕâ¸ö±í´ïʽû´í
}

int
main(void)
{
printf("%f\n",round(3.141522967,4));
}

这个函数在我这里可以运行正确的,不过要注意float只能精确到8位
回复
sonic_andy 2004-11-01
(int)(v * temp + 0.5) / temp 0.130000
temp 100.000
v 0.126450
n 2.00000
f 0.130000
我运行的结果是这个,应该没错吧?
回复
vioy 2004-11-01
四舍五入的结果必须用INT类型保存!
回复
相关推荐
发帖
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
帖子事件
创建了帖子
2004-11-01 09:27
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……