将浮点数分配给 long double 时,它​​的值会发生啥变化?

Posted

技术标签:

【中文标题】将浮点数分配给 long double 时,它​​的值会发生啥变化?【英文标题】:What happens to the value of a floating point number when it's assigned to a long double?将浮点数分配给 long double 时,它​​的值会发生什么变化? 【发布时间】:2016-06-22 19:56:43 【问题描述】:

编辑:我意识到我正在使用类型 long double而不仅仅是 double 确实会有所作为。我还在下面的程序中添加了一个示例,该示例重现了相关错误。

注意:我目前正在使用 C++11 并使用 GCC 进行编译。

我正在处理结果在以下两个计算之间有所不同的情况:

value1 = x * 6.0;

double six = 6.0;
value2 = x * six;

value1 != value2

以上所有变量的类型均为long double

本质上,当我在实际计算中使用 6.0 时,我写了一行代码给了我一个错误的答案。然而,如果我先将 6.0 分配给 long double 类型的变量,然后在计算中使用该变量,我会收到正确的结果。

我了解浮点运算的基础知识,并且我想很明显,当它被分配给 long double 类型时,6.0 的位发生了一些事情。

来自我的实际程序的示例(我保留了计算以确保错误是可重现的):

#include <iomanip>
#include <math.h>

long double six = 6.0;
long double value1;
long double value2;

value1 = (0.7854 * (pow(10, 5)) * six * (pow(0.033, 2)) * 1.01325 * (1.27 * 11.652375 / 1.01325 - 1.0));
value2 = (0.7854 * (pow(10, 5)) * 6.0 * (pow(0.033, 2)) * 1.01325 * (1.27 * 11.652375 / 1.01325 - 1.0));

std::cout << std::setprecision(25) << value1 << std::endl;
std::cout << std::setprecision(25) << value2 << std::endl;

输出在哪里:

7074.327896870849993415931
7074.327896870850054256152

另外,我了解浮点计算如何仅将精度保持在一定数量的位(因此设置如此高的精度不应该影响结果,例如,在 15-17 位之后,如果数字变化确实很重要,但不幸的是这 确实影响我的计算)。

问题:为什么以上两个代码段会产生(轻微)不同的结果?

注意:我不是简单地将这两个数字与 == 和接收 false 进行比较。我刚刚使用 setprecision 将它们打印出来并检查每个数字。

【问题讨论】:

6.0 已经是double 类型。 即使只有双精度或浮点数,您也不应该依赖3.0 + 3.0 == 6.0 @PaulWarnick 我已经撤回了我的重复投票,因为我知道你实际上在问什么。但是我无法重现,您能提供一个工作示例吗? @PaulWarnick 你能试着把文字变成一个长的双倍(即6.0L)吗? 我无法找到重复项(我确信肯定有一些),所以我提供了一个答案。我认为主要是始终提供一个重现错误的工作示例。那你就不会出错了:) 【参考方案1】:

我认为这里的问题是促销之一。

long double six = 6.0;
long double value1;
long double value2;

value1 = (0.7854 * (pow(10, 5)) * six * (pow(0.033, 2)) * 1.01325 * (1.27 * 11.652375 / 1.01325 - 1.0));
value2 = (0.7854 * (pow(10, 5)) * 6.0 * (pow(0.033, 2)) * 1.01325 * (1.27 * 11.652375 / 1.01325 - 1.0));

查看第二个计算,我们注意到表达式中的每个项都是 double 类型。这意味着整个表达式将被评估为 双精度

然而,first 计算包含six 类型的变量long double。这将导致 整个表达式long double 的更高精度计算。

因此,计算精度的这种差异可能是造成差异的原因。整个第一个表达式提升long double 精度,但第二个计算仅计算为double 精度。

事实上,对代码进行简单的更改就可以证明这一点。如果我们通过编写6.0L 将术语6.0 的类型从double 更改为long double,我们将得到相同的结果,因为两个 表达式现在计算为相同的精度:

value1 = (0.7854 * (pow(10, 5)) * six * (pow(0.033, 2)) * 1.01325 * (1.27 * 11.652375 / 1.01325 - 1.0));
value2 = (0.7854 * (pow(10, 5)) * 6.0L * (pow(0.033, 2)) * 1.01325 * (1.27 * 11.652375 / 1.01325 - 1.0));

【讨论】:

以上是关于将浮点数分配给 long double 时,它​​的值会发生啥变化?的主要内容,如果未能解决你的问题,请参考以下文章

将双精度数分配给 C 中的 int 变量的非直观结果

将 unsigned int(使用 .size())分配给一维浮点向量

java - 当没有接受long的方法时,为啥java将long参数提升为float/double?

java数据类型转换

数据类型转换&运算符

Lua 浮点运算