在linux上使用fpu_control.h实现双精度
我正在尝试将一段特定的代码从solaris移植到Linux。在这个过程中,我发现linux上的精度不同,它是扩展精度,我们需要显式地将其设置为双精度。要实现此功能,请找到fpu_control.h库中的函数fpu_GETCW和fpu_SETCW函数。但即使在这之后,精度也没有被正确设置。 代码片段在linux上使用fpu_control.h实现双精度,c,linux,fpu,decimal-precision,C,Linux,Fpu,Decimal Precision,我正在尝试将一段特定的代码从solaris移植到Linux。在这个过程中,我发现linux上的精度不同,它是扩展精度,我们需要显式地将其设置为双精度。要实现此功能,请找到fpu_control.h库中的函数fpu_GETCW和fpu_SETCW函数。但即使在这之后,精度也没有被正确设置。 代码片段 long double power = 1.0; #ifdef __linux fpu_control_t mask; _FPU_GETCW(mask); mask &
long double power = 1.0;
#ifdef __linux
fpu_control_t mask;
_FPU_GETCW(mask);
mask &= ~(_FPU_EXTENDED & _FPU_SINGLE);
mask |= _FPU_DOUBLE;
_FPU_SETCW(mask);
power *= 0.1;
#endif
打印电源时,该值为
功率=0.100000000000000551151231257827
但是,我希望power的值为0.1
在编译时,我还使用了use-DDouble。有人能告诉我出了什么问题吗。你特别要求一个
长双精度
,而你应该想要普通的双精度
。如果您的硬件是Intel x86/x86-64 CPU,则通过FPU的计算将以80位精度执行
否则:尝试使用gcc标志:-mfpmath=sse
,它将停止使用FPU,并且您的操作将以64位(也称为双精度)的精度执行
注:
即使在Solaris中,也很可能得到了0.1
的不精确表示形式(没有精确的表示形式),但是输出值的方式通过打印指定数量的十进制数字隐藏了这种不精确性
我希望功率值为0.1
通常不可能满足OP的期望
double
和long double
不能存储所有可能的数字。double
可以准确地编码大约264个不同的数字,因为它通常使用64位。long double
可以精确编码264、280或2128个不同的数字
使用时,0.1不能准确地编码为双精度。这不是264个确切数字中的一个。相反,double x=0.1
将使用最接近的备选方案初始化x
:
Exact value 0.1000000000000000055511151231257827021181583404541015625
OP's printed value 0.1000000000000000055511151231257827
下一个相近的选择是
0.09999999999999999167332731531132594682276248931884765625
这不是一个
double
vslong double
问题。我不明白这一点。如果希望power
成为双精度变量,为什么要将其声明为long double
?我假设您知道,无论精度级别如何,0.1都不能精确地表示为浮点值。您是对的,但这种乘法是在循环内部发生的,基于某些条件。也就是说,有时我们可能会做5次或3次乘法。因此,每次乘法后,值都会发生变化,即,1、.01.001、.0001,然后根据外部因素进行变化。因此code@girishs您得到的数字是最接近十进制0.1的双精度二进制浮点。有什么问题吗?它尽可能精确。@art但是当我打印值时,它也是一个巨大的数字,如果我以后用这个数字做一些算术运算,我会得到一个不同的数字,对吗?我的期望是获得与Solaris相同的值。(抱歉,我可能遗漏了一些内容)@girishs您应该将相关代码显示为a,以及输入、预期输出和实际输出。在32位上,默认值通常为x87,表示形式为80位。在amd64上,默认值通常为SSE.ok,仅供我理解。设置FPUCW有什么用?我认为这会将精度从extended(在linux中,也如您所指出的)设置为double?“这不管用吗?”Girish使用。它不会起作用。因为这个答案断言这不是一个double
vslong double
问题。改变精度没有帮助。它可能使一种价值观“起作用”,但其他价值观将失败。解决方案是“我们需要显式地将其设置为双精度。”即您已经准备好获得double
精度。IOWs,0.10000000000000055551151231257827没有错。这就是您应该使用double
精度获得的结果。