将浮点数分配给 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 时,它的值会发生啥变化?的主要内容,如果未能解决你的问题,请参考以下文章
将 unsigned int(使用 .size())分配给一维浮点向量