不久前我写了一个程序,它使用了一些阶乘函数.我使用long double数据类型来支持"相对"大数字.
现在,我从代码块改为Visualstudio 2010,我想知道为什么我的程序不再工作,直到我在一些研究中意识到MS已经放弃了长双数据类型.这有什么特别的原因吗?对我而言,它看起来非常像技术方面的倒退.
有没有其他选择?(我也很乐意使用boost库中的替代品).
可能重复:
long double vs double
我是编程新手,我无法理解C和C++中long double和double之间的区别.我试图谷歌它但无法理解它并感到困惑.谁能请帮忙.
是的,我的意思是说80位.这不是一个错字......
我对浮点变量的经验总是涉及4字节的倍数,如单音(32位),双音(64位)和长双音(我已经看到它被称为96位或128位).这就是为什么当我遇到一些代码来读取和写入AIFF(音频交换文件格式)文件时遇到80位扩展精度数据类型时我有点困惑:选择了一个扩展精度变量来存储采样音轨的速率.
当我浏览维基百科时,我发现上面的链接以及IEEE 754-1985标准摘要中的80位格式的简要提及(但不在IEEE 754-2008标准摘要中).看来,在某些架构上,"扩展"和"长双"是同义词.
我没有遇到的一件事是使用扩展精度数据类型的特定应用程序(当然,AIFF文件采样率除外).这让我想知道:
我们正在使用C语言中的数字例程库.我们还不确定是否可以使用单精度(float)或double(double),因此我们将类型定义SP为别名,直到我们决定:
typedef float SP;
Run Code Online (Sandbox Code Playgroud)
当我们运行我们的单元测试时,它们都会通过我的机器(一个64位的Ubuntu),但它们在我的同事(一个错误地安装在64位机器上的32位Ubuntu)上失败了.
使用Git的bisect命令,我们发现确切的差异开始在他的机器和我的机器之间产生不同的结果:
-typedef double SP;
+typedef float SP;
Run Code Online (Sandbox Code Playgroud)
换句话说,从双精度到单精度会在我们的机器上产生数值上不同的结果(在最坏情况下约为1e-3相对差异).
我们相当肯定,我们永远不会将无符号的整数与负数签名的整数进行比较.
为什么数字例程库会在32位操作系统和64位系统上产生不同的结果?
澄清
我担心我可能不够清楚:我们有2f3f671使用双精度的Git提交,并且单元测试在两台机器上同样通过.然后我们有git的承诺46f2ba,我们改为单精度,这里的测试仍然通过64位的计算机上,但不能在32位机器上.
以下代码将在x86 32位计算机上为变量"e"和"f"输出不同的结果,但在x86 64位计算机上会产生相同的结果.为什么?从理论上讲,正在评估相同的表达,但从技术上讲,它不是.
#include <cstdio>
main()
{
double a,b,c,d,e,f;
a=-8988465674311578540726.0;
b=+8988465674311578540726.0;
c=1925283223.0;
d=4294967296.0;
e=(c/d)*(b-a)+a;
printf("%.80f\n",e);
f=c/d;
f*=(b-a);
f+=a;
printf("%.80f\n",f);
}
Run Code Online (Sandbox Code Playgroud)
注意...使用'gcc -m32'可以生成32位x86代码,谢谢@Peter Cordes /sf/users/15689271/
也可以看看
boost :: random :: uniform_real_distribution应该是跨处理器的相同吗?
---为用户Madivad更新
64 bit output
-930037765265417043968.00000...
-930037765265417043968.00000...
32 bit output
-930037765265416519680.00000...
-930037765265417043968.00000...
Run Code Online (Sandbox Code Playgroud)
这个python代码可以给出"数学上正确"的输出
from fractions import Fraction
a=-8988465674311578540726
b=8988465674311578540726
c=1925283223
d=4294967296
print "%.80f" % float(Fraction(c,d)*(b-a)+a)
-930037765265416519680.000...
Run Code Online (Sandbox Code Playgroud) 我发现一些复杂计算的结果不匹配.当我彻底观察到中间结果时,它的std :: pow函数会产生不匹配.以下是输入/输出.
long double dvalue = 2.7182818284589998;
long double dexp = -0.21074699576017999;
long double result = std::powl( dvalue, dexp);
Run Code Online (Sandbox Code Playgroud)
64位 - >结果= 0.80997896907296496和32位 - >结果= 0.80997896907296507
我正在使用VS2008.我已尝试过其他功能的pow功能,需要很长的双倍并返回长双,但仍然看到相同的差异.
double pow( double base, double exponent );
long double powl( long double base, long double exponent );
我已经阅读了一些关于此的信息:
Intel x86处理器内部使用80位扩展精度,而double通常是64位宽.不同的优化级别会影响来自CPU的浮点值保存到内存中的频率,从而将80位精度舍入为64位精度.或者,使用long double类型,通常在gcc上为80位宽,以避免从80位到64位精度的舍入.
有人能让我清楚地了解差异和克服这种差异的方法.