怪事,一个简单的计算在不同情况下结果不同

hind24 2010-08-08 03:00:28
在自定义线程里,有如下代码
int a = 10;
double b = 0.01;
int c = a/b;

结果是999
把c定义成double就没问题,再赋给int也没问题
浮点型丢失精度也不能这样吧

但是在VCL的按钮事件里写同样的代码,结果却是1000

是不是线程还要设置什么?以后再出怪事不能在窗体里写代码验证了……
...全文
154 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
hind24 2010-08-26
  • 打赏
  • 举报
回复
再聊聊嘛,好不容易说到正题上
勉励前行 2010-08-25
  • 打赏
  • 举报
回复
浮点数的計算結果一定程序上同CPU相關,只保障有效位數,而且這個有效位置是二進制的有效位數,

如果你要每次計算結果一致,你禁用CPU的浮點指令集重新編譯,這樣結果會比較一致。

因為 不同的數轉化為二進制後,在有效位內,其二進制形式是相同的,CPU采用何種策略進行快速計算,是它的權利,只要保障有效位數內是准確的即可。

周药师 2010-08-25
  • 打赏
  • 举报
回复
这个帖子还不结啊?
hind24 2010-08-25
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 ppower 的回复:]

浮点数的計算結果一定程序上同CPU相關,只保障有效位數,而且這個有效位置是二進制的有效位數,

如果你要每次計算結果一致,你禁用CPU的浮點指令集重新編譯,這樣結果會比較一致。

因為 不同的數轉化為二進制後,在有效位內,其二進制形式是相同的,CPU采用何種策略進行快速計算,是它的權利,只要保障有效位數內是准確的即可。
[/Quote]看来这个似乎超出了C++范围了哈,但是我发现窗体内和工作线程内有不同,是不是它们分别对CPU的运算方式有不同影响呢?那这个就比较有趣了
勉励前行 2010-08-24
  • 打赏
  • 举报
回复
這本來就是浮點數的問題。

在浮點數轉換到整數時就會有丟失,必須自行處理這個問題。

一般,加一個極小的小數(7位左右)後,再轉換成整數就行了。
加一個極小的小數,不影響浮點數的有效位數,也就是不影響浮點數的值,但影響其在內存中的表達方式。
inline int doubletoint(double V)
{
return V > 0 ? V + 0.0000001 : V - 0.0000001 ;
}
int c = doubletoint(a/b);//這樣就行了。

如果浮點數大於其所能表達的精度,是有誤差的。
使用浮點數要知道浮點數的問題。

如果小數點只有4位的話, 可以使用 Currency 類型,就沒這問題了。
int a = 1;
Currency b = 0.01 ;
Currency v = a/b ;
但注意:Currency類型只保障小數點後4位。
bigfog 2010-08-24
  • 打赏
  • 举报
回复
浮点数就是这样的,简单的取整就把后面截断了
hind24 2010-08-24
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 ouygg 的回复:]

int a = 10;
double b = 0.01;
int c = a/b; ===>这里默认强制转换有问题。
应该为:
int a = 10;
double b = 0.01;
int c = (double a)/b;
[/Quote]又有大牛回复,不胜荣幸!

不过,这个代码在2010的工作线程里结果仍然是999

本来挺无聊一问题,没想到大家理解得都不一样啊
hind24 2010-08-24
  • 打赏
  • 举报
回复
浮点不能表示所有数值,很多人都知道,各种解决方法网上也能搜罗到一堆,谢谢各位不吝赘述

鄙人关心的是,不同编译器在不同条件下有规律的出现不同结果,有什么更深层次的原因

相同代码,你说一定会丢失精度,但有的环境下就是不丢失(窗体内和工作线程内就不一样)

你认为手动转换类型能避免,可能在你的开发环境下可以,换一个就不行

很简单的计算过程,能不能用语言的标准来解释其规律,而不是单纯去绕开这个问题,因为现象已经跟理解有了偏差

避免这个问题的方法无数,在下在这里提出无非是想听听大牛们更深入的看法
zhaozilongg 2010-08-23
  • 打赏
  • 举报
回复
不会吧
痞子酷 2010-08-23
  • 打赏
  • 举报
回复
int a = 10;
double b = 0.01;
int c = a/b; ===>这里默认强制转换有问题。
应该为:
int a = 10;
double b = 0.01;
int c = (double a)/b;
wendy97971 2010-08-23
  • 打赏
  • 举报
回复
这个问题还没有碰到过,值得学习一下
明朝2013 2010-08-23
  • 打赏
  • 举报
回复
隱式轉換了
bigfog 2010-08-09
  • 打赏
  • 举报
回复
C语言在浮点中就有这个问题,可以用技巧弥补一下
hind24 2010-08-08
  • 打赏
  • 举报
回复
嘿嘿,也不是绝对不可能,不就是嫌麻烦么,全用long double就行了,但是含有大量计算的程序经常需要用到隐式转换带来的方便,也需要用区分开的类型所带来的各种优势

问题在于理论上提前进行转换和计算时编译器隐式转换原理应该是一致的,为何结果却大相径庭,而且在不同条件下结果不同,我倒不是不愿意写复杂的代码,而是这其中肯定有别的道理,所以才向大家请教啊

周药师 2010-08-08
  • 打赏
  • 举报
回复
"可是有时候不得不把不同的类型放在一起计算,而且这个计算在不同条件下结果不一样,"
不得不?
任何事情都可以自己控制的

void __fastcall TForm1::FormCreate(TObject *Sender)
{
int a = 10;
double b = 0.01;
double c = a/double(b);
int d = c ;
ShowMessage(c) ; //1000
ShowMessage(d) ;//1000
}


hind24 2010-08-08
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 dxkh 的回复:]

C/C++ code

void __fastcall TForm1::Button1Click(TObject *Sender)
{
int a = 10;
double b = 0.01;
int c = int((double)a/b);
}
[/Quote]在线程里结果仍然是999

药师说的对,不同类型一起计算确实会发生一些跟预期不一样的结果,要尽量避免。可是有时候不得不把不同的类型放在一起计算,而且这个计算在不同条件下结果不一样,我有时改了代码,重新编译后第一次计算结果都不对,第二次以后就正常了,是不是编译器要设置?
我来看看CB 2010-08-08
  • 打赏
  • 举报
回复

void __fastcall TForm1::Button1Click(TObject *Sender)
{
int a = 10;
double b = 0.01;
int c = int((double)a/b);
}


周药师 2010-08-08
  • 打赏
  • 举报
回复
我是在6.0 上测试的
我这里 没有2010
建议用同一类进行数学运算
hind24 2010-08-08
  • 打赏
  • 举报
回复
这次真的杯具了,我的确实是1000,测试代码跟你的完全一样
我是2010

我的理解是混合类型计算时有得会被提升,实际上计算的时候那两个整型都转成double了,最后结果肯定也是1000(double的),然后又赋给整型,这个过程中没理由丢失精度啊,而且把0.01变成0.001结果就是9999,反正总是少1
周药师 2010-08-08
  • 打赏
  • 举报
回复
算数计算 最好用同一类型的

void __fastcall TForm1::Button1Click(TObject *Sender)
{
double a = 10;
double b = 0.01;
double c = a/b;
ShowMessage(FloatToStr(c));//显示1000
}

加载更多回复(1)

604

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder VCL组件使用和开发
社区管理员
  • VCL组件使用和开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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