cb编程n年,今天遇到的一个非常奇怪又非常简单的问题,哪位大侠解释一下原因.

luo73 2005-07-29 01:01:15
有下列代码:
static const int A[]={4, 8};
static const int B = 4;

int aa, bb;
aa = (int)(A[0]*90/360.0);
bb = (int)(B *90/360.0);

int C, cc;
C = A[0];
cc = (int)(C*90/360.0);
printf("@: aa=%d, bb=%d, cc=%d.\n", aa, bb, cc);

运行结果不是1,1,1,而是:

@: aa=0, bb=1, cc=0.

为什么会这样?
...全文
410 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
luo73 2005-08-02
  • 打赏
  • 举报
回复
想不到这个问题把季大侠(2003年我经常学习您的帖子)和Maconel大侠都惊动了,呵呵。
还是有点晕,结帖算了。
zhaoxinghan 2005-08-01
  • 打赏
  • 举报
回复
类型转换啊,我以前一个程序也遇到同样的问题,想了半天才明白。
Waiting4you 2005-07-31
  • 打赏
  • 举报
回复
晕~~
xili 2005-07-30
  • 打赏
  • 举报
回复
俺现在对vc的行为有点纳闷了,

难道它将3句都优化成编译器计算了?
似乎不可能,尤其第3句的 c 不是const.

那么他就是对 int/float 的算法做得更加精致了?

俺不太用vc,有知道的大贤请指教.
xili 2005-07-30
  • 打赏
  • 举报
回复
看来Maconel说的对

因为 B是 const int
所以 bb = (int)(B *90/360.0); 这一句在编译器里就计算出结果了,
即也看做常数了.

如楼主所说, 360.0在程序中其实是个变量, 因此不必担心计算会出现误差.
  • 打赏
  • 举报
回复
类型转化时的问题, 需要注意啊!! 楼主提供的好注意事项! Mark之, 谢谢楼主了!
currentopen 2005-07-29
  • 打赏
  • 举报
回复
futulove(福途£爱):

float aa, bb;
aa = (int)(A[0]*90/360.0);
bb = (int)(B *90/360.0);

上面代码中(int)似乎没有必要。因为在下面这句话中有(int),
printf("@: aa=%d, bb=%d, cc=%d.\n", (int)aa, (int)bb, (int)cc);

你看呢?
FengSC 2005-07-29
  • 打赏
  • 举报
回复
正常正常
Waiting4you 2005-07-29
  • 打赏
  • 举报
回复
好奇怪,用VC是什么结果?
futulove 2005-07-29
  • 打赏
  • 举报
回复
应该是转换的时候出的错误,要是把所有的都换成flost和%f的话就没有问题了
或者像下面的也可以
static const int A[]={4, 8};
static const int B = 4;

float aa, bb;
aa = (int)(A[0]*90/360.0);
bb = (int)(B *90/360.0);

float C, cc;
C = A[0];
cc = (int)(C*90/360.0);
printf("@: aa=%d, bb=%d, cc=%d.\n", (int)aa, (int)bb, (int)cc);
Persistent8813 2005-07-29
  • 打赏
  • 举报
回复
既然用整数,为什么不用360?
Persistent8813 2005-07-29
  • 打赏
  • 举报
回复
二楼用什么环境调试的?BCB6是 @: aa=0, bb=1, cc=0.
一定是强制类型转换由float 到 int 时有误差所致
jishiping 2005-07-29
  • 打赏
  • 举报
回复
其实很正常。因为是浮点数,所以存在误差。A[0]*90/360.0的值可能刚好是1.0,也可能是0.999999这样的值,也可能是1.000001这样的数。如果是类似于0.999999这样的数,转换为整数后就变成了0。所以我在程序中经常采用类似下面的代码:
aa = (int)(A[0]*90/360.0+0.0001); //转换为整数前,加一个小的数字
这样得到的值,就是楼主期望得到的数值了。
Maconel 2005-07-29
  • 打赏
  • 举报
回复
晕,上边的发错了。
我原来说的是:

楼上的几位,我想楼主要讨论的不是该如何去做,而是这样做为什么会有问题。
Maconel 2005-07-29
  • 打赏
  • 举报
回复
想5个星星就难咯,如果csdn不改版,永远都不行,3星以上跟分数没有关系的
Maconel 2005-07-29
  • 打赏
  • 举报
回复
我们运行起来,然后看看cpu中的代码:
在aa = (int)(A[0]*90/360.0);处的asm代码为:
imul eax,dword ptr [SysInit::_16387 + 0x18],0x51
mov [ebp-0x14],eax
fild dword ptr [ebp-0x14]
fld tbyte ptr [0x004013ec]
fmulp st(1)
call CC3260MT.__ftol
mov [ebp-0x04],eax

在bb = (int)(B *90/360.0);处的代码为:
mov [ebp-0x08],0x00000001

我对汇编不大懂,不过还是可以看出来,在运行
aa = (int)(A[0]*90/360.0);时,是真正的去计算这个算式,
而运行
bb = (int)(B *90/360.0);时,是直接将结果1给了bb,换成c的代码,就是这样:
bb = 1;
不用问,着肯定是编译器优化了。至于A[0]为什么没有优化,我想可能是因为他是个数组,

要得到他的值比较麻烦(还要多一次寻址),所以就采用了真正运算的方法,结果由于符点

数的精度问题,导致结果为0。

将代码改为这样:
int aa, bb;
int n = 90;
aa = (int)(A[0]*n/360.0);
bb = (int)(B *n/360.0);
用一个变量来代替那个90,因为算式里有了变量,所以编译器就没有优化,我用bcb6.0来测试,最后输出的结果为:
@: aa=0, bb=0, cc=0.
ITsignal 2005-07-29
  • 打赏
  • 举报
回复
从来不用float,double才是好的选择
xjq2003 2005-07-29
  • 打赏
  • 举报
回复
我真的不知道为什么,昨天刚遇到这样的事!
ITsignal 2005-07-29
  • 打赏
  • 举报
回复
从来不用float,小数都用double.
xjq2003 2005-07-29
  • 打赏
  • 举报
回复
请用下面的方法显示,如果还不对,就不用给我分了!

printf("@: aa=%d, ", aa);
printf("@: bb=%d, ", bb);
printf("@: cc=%d.\n", cc);

这样肯定没有问题,不要问为什么!!
加载更多回复(5)

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧