讨论:关于强制类型转换

lyyrw 2003-12-19 11:03:51
程序如下:
AnsiString a;
a = "800000";
Edit1->Text = AnsiString( (int) ( a.ToDouble() / 1000 ) );
Edit2->Text = AnsiString( (int) ( a.ToDouble() ) / 1000 );
a = "800001";
Edit3->Text = AnsiString( (int) ( a.ToDouble() / 1000 ) );
Edit4->Text = AnsiString( (int) ( a.ToDouble() ) / 1000 );
Edit1中的结果是799,而Edit2中的结果是800。问题应出在
(int) ( a.ToDouble() / 1000 ) );与
(int) ( a.ToDouble() )/ 1000 );的区别
可是Edit3和Edit4的结果相同
计算1000的倍数的不到正确的结果,反而不是1000的倍数得到了正确的结果?
搞不懂,大家讨论讨论?
...全文
78 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyyrw 2003-12-24
  • 打赏
  • 举报
回复
up
lyyrw 2003-12-23
  • 打赏
  • 举报
回复
up
constantine 2003-12-21
  • 打赏
  • 举报
回复
study
aliker 2003-12-21
  • 打赏
  • 举报
回复
double x = 800000;
int a = (int) ( x / 1000 );
int c = (int) (x) / 1000;
double y = 800000 / 1000;
int b = (int) y;

a = 799
b = 800
c = 800
我试了
只要把分子分母同时扩大或缩小就不会会出现上诉情况。
扩大十倍
double x = 8000000;
int a = (int) ( x / 10000 );
int c = (int) (x) / 10000;
double y = 8000000 / 10000;
int b = (int) y;

a = 800
b = 800
c = 800
缩小十倍
double x = 80000;
int a = (int) ( x / 100 );
int c = (int) (x) / 100;
double y = 80000 / 100;
int b = (int) y;

a = 800
b = 800
c = 800
缩小100倍、1000倍都一样。
lyyrw 2003-12-20
  • 打赏
  • 举报
回复
但不明白的是a=800000,即便是浮点数那也是800000.0000000000怎么肯能是799999.9999999999那,计算机是怎么进行存储的?
huoniao1976 2003-12-20
  • 打赏
  • 举报
回复
同意“蓝鲸--优秀得郁闷的鱼”说的


如果参加运算的两个数中有一个是double型,则结果是Double型,
(int)( a.ToDouble() / 1000 );
(int)( a.ToDouble()) / 1000;是整数运算,两个整数相除结果为整数,而舍去小数部分。
aliker 2003-12-20
  • 打赏
  • 举报
回复
因为浮点数的存储和整型数不一样。
32位字长的机器中,数采用浮点表示,符号位占1位,尾数位占23位,阶符占1位,阶码占7位。阶码用移码表示,尾数用补码表示。
浮点表示
N=M*RE
M:尾数,R:基数,E:指数(阶码)
0.11010001 2^10100 = 0 1 0010100 11010001000000000000000
阶符(0) 阶符(1) 阶码(2-8) 尾数(9-31)
对于8000.0,计算机在存储时会对它做格式化的。
(假设8000.0=0.1234*2^123)
计算机会先把8000转化成上面的格式,前面的0.1234必须小于0.5,后面是2的123次幂
然后在转化成下面的形式
(假设0.1234=0.1110011,123=1110101)
那么8000.0=0.1110011 2^ 1110101
最后8000.0= 0 1 1110101 11001100000000000000000
存储在计算上的就是01111010111001100000000000000000
因为8000不能刚好表示成x*2^y,所以只能用近似值,比如7999.9999来表示。
具体怎么转,你可以看下其他参考书,我也不是很清楚。
penu 2003-12-19
  • 打赏
  • 举报
回复
所以必须先将计算结果先保存到一个变量中,再进行类型转换,才不会出现精度丢失!
lyyrw 2003-12-19
  • 打赏
  • 举报
回复
那问题是出在(int)上???
penu 2003-12-19
  • 打赏
  • 举报
回复
我知道了,见下:
double x = 800000;
int a = (int) ( x / 1000 );

double y = 800000 / 1000;
int b = (int) y;

情况好象 a 应该等于 b ,而实际情况是:
a == 799
b == 800

!!!
penu 2003-12-19
  • 打赏
  • 举报
回复
更正一下,整数除法也是只取整数部分。
我现在有点不明白的是:
AnsiString a,b,c,d;
double e,f;
int g;
a = "800000";
Edit1->Text = a;
e = a.ToDouble();
f = a.ToDouble() / 1000;
g = (int)(f);
b.sprintf("%f",e);// 显示 a.ToDouble()
Edit2->Text = b;
c.sprintf("%f",f);// 显示 a.ToDouble()/1000
Edit3->Text = c;
d.sprintf("%d",g);// 显示 (int)(a.ToDouble()/1000)
Edit4->Text = d;
// 另一种方式计算显示
Edit5->Text = AnsiString(a.ToDouble());// 显示 a.ToDouble()
Edit6->Text = AnsiString(a.ToDouble() / 1000);// 显示 a.ToDouble()/1000
Edit7->Text = AnsiString((int)(a.ToDouble() / 1000));// 显示 (int)(a.ToDouble()/1000)

为什么会:
显示结果为:
Edit1:800000
Edit2:800000.000000
Edit3:800.000000
Edit4:800

Edit5:800000
Edit6:800
Edit7:799 // !!!!! 为什么???
lyyrw 2003-12-19
  • 打赏
  • 举报
回复
还是不明白,a是800000。即便有小数,也是0呀,怎么会四舍五入那
为什么会有精度的损失
penu 2003-12-19
  • 打赏
  • 举报
回复
显示结果为:
Edit1:800000
Edit2:800000.000000
Edit3:800.000000
Edit4:800

Edit5:800000
Edit6:800
Edit7:799 // !!!!!
penu 2003-12-19
  • 打赏
  • 举报
回复
好象有些蹊跷,大家试试下面程序:
AnsiString a,b,c,d;
double e,f;
int g;
a = "800000";
Edit1->Text = a;
e = a.ToDouble();
f = a.ToDouble() / 1000;
g = (int)(f);
b.sprintf("%f",e);// 显示 a.ToDouble()
Edit2->Text = b;
c.sprintf("%f",f);// 显示 a.ToDouble()/1000
Edit3->Text = c;
d.sprintf("%d",g);// 显示 (int)(a.ToDouble()/1000)
Edit4->Text = d;
// 另一种方式计算显示
Edit5->Text = AnsiString(a.ToDouble());// 显示 a.ToDouble()
Edit6->Text = AnsiString(a.ToDouble() / 1000);// 显示 a.ToDouble()/1000
Edit7->Text = AnsiString((int)(a.ToDouble() / 1000));// 显示 (int)(a.ToDouble()/1000)
huoniao1976 2003-12-19
  • 打赏
  • 举报
回复
学习
那带小数位,小数位也是0呀,那为什会变成799呢?
penu 2003-12-19
  • 打赏
  • 举报
回复
注意:(int)类型转换:只取整数部分
整数除法:四舍五入取整
penu 2003-12-19
  • 打赏
  • 举报
回复
(int)(a.ToDouble()/1000):
(1)a.ToDouble: 799999.?
(2)/1000 : 799.?
(3)(int) : 799

(int)(a.ToDouble())/1000:
(1)a.ToDouble: 799999.?
(2)(int) : 799999
(3)/1000 : 800
书生 2003-12-19
  • 打赏
  • 举报
回复
楼上,我用楼主的测试,第一个确实799。 BCB6+2000Server.
ToDouble()这个函数规定了,String 必须带有小数部分。
书生 2003-12-19
  • 打赏
  • 举报
回复
ToDouble converts the string to a floating-point value. The string must consist of an optional sign (+ or -), a string of digits with an optional decimal point, and an optional 'E' or 'e' followed by a signed integer. Leading and trailing blanks in the string are ignored. The DecimalSeparator global variable defines the character that must be used as a decimal point. Thousand separators and currency symbols are not allowed in the string. If the string doesn't contain a valid value, an EConvertError exception is thrown.

函数说明里:String必须带有小数部分。 ^&^
yangguo_god 2003-12-19
  • 打赏
  • 举报
回复
我测试后结果都为800,bcb6,win2000
加载更多回复(14)

13,825

社区成员

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

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