Cpt*_*nic -4 c++ windows floating-point
我知道这些浮点问题可能是堆栈溢出时最常问的问题,但我找不到看起来像我的东西.在windows(visual studio)编译为32位,如果我这样做:
double lnA = 1448481410.0;
double lnB = 0.75599998235702515;
double lnC = lnA + lnB;
Run Code Online (Sandbox Code Playgroud)
我得到lnC = 1448481408.0000000.由于浮点表示,我可以理解一个小的差异,但我不明白为什么lnA - lnC == 2?
更新:所以这是使用Visual Studio 2010的实际输出:这是一个MFC应用程序,这就是我使用TRACE的原因.
double lnA = 1448481410.0;
double lnB = 0.75599998235702515;
double lnC = lnA + lnB;
TRACE("A = %f B = %f C = %f A - C = %f\n",lnA, lnB, lnC, lnA - lnC);
Run Code Online (Sandbox Code Playgroud)
A = 1448481410.000000 B = 0.756000 C = 1448481408.000000 A - C = 2.000000
UPDATE2:在尝试制作如下所示的最小完整示例时,我没有看到同样的问题.只有当它是我的大型应用程序的一部分.有任何想法吗?
#include <iostream>
int main() {
double lnA = 1448481410.0;
double lnB = 0.75599998235702515;
double lnC = lnA + lnB;
std::cout << "A: " << lnA << "B: " << lnB << "C: " << "Diff: " << lnA - lnC << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
经过一番调查后,我得出的结论是,您的代码可能会令人困惑,float并且double(或查看与您实际发布的代码不同的代码输出).
这对我有用:
#include <iostream>
int main()
{
double lnA = 1448481410.0;
double lnB = 0.75599998235702515;
double lnC = lnA + lnB;
std::cout << std::fixed << "A:" << lnA << " B:" << lnB << " C:" << lnC << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
生产:
$ ./a.out
A:1448481410.000000 B:0.756000 C:1448481410.756000
Run Code Online (Sandbox Code Playgroud)
现在,正如Soulsabr在评论中所说,如果我们使用float而不是double,结果是不同的:
只有这些行改变了:
float lnA = 1448481410.0;
float lnB = 0.75599998235702515;
float lnC = lnA + lnB;
$ ./a.out
A:1448481408.000000 B:0.756000 C:1448481408.000000
Run Code Online (Sandbox Code Playgroud)
这是因为float在典型系统中,a的比特数是32比特,它被分成8比特的指数,1比特的符号和23比特[加上一个隐藏]用于尾数.所以值是S * M * 2^E,S符号在哪里,M是尾数,E是指数.大小M为23位,因此可用于精确描述高达约8百万的值.我们可以使用E来移动值,但无论我们选择什么值,在数字内可以改变的最小值是x/8百万实际值的下一个更大的整数.因此,"有所作为"的最小值中有1400万变为+/- 2.添加1或更少将完全没有效果.
的double代码"作品",因为一个64位双具有53位尾数,其允许值设定为+/- 1/^的实际值,这是一个更大的值的53,并且允许进行更精确的验算.但要取得足够大和足够小的价值,如果它们足够远,我们就会遇到同样的问题.这只是浮点值如何工作的问题.你只有这么多位.有"大数学"库允许更多位,("无限",受内存可用),但当然,值越大,计算速度越低,对于大多数事情,1/2 ^ 53价值"足够好".
编辑(根据OP的评论):
如果在使用x87指令时将FPU设置为"舍入到32位",则表示即使使用64位浮点值进行计算,也会发生与"使用浮点数"类似的影响,中间结果舍入为32位精度.根据上面的评论,这似乎是一个特殊的软件产品,做了一些"魔术"来实现这一点,并有一个简单的解决方法.
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |