【发布时间】:2020-02-10 02:05:02
【问题描述】:
我正在尝试编写一个程序,使用该系列来计算 PI 的值。用户将输入希望程序计算系列的距离,然后程序应输出其计算的 PI 值。我相信我已经成功地为此编写了代码,但是它不适用于大数字,并且只给了我几个小数位。当我尝试使用cout << fixed << setprecision(42); 时,它只是给了我“nan”作为 PI 的值。
int main() {
long long seqNum; // sequence number users will input
long double val; // the series output
cout << "Welcome to the compute PI program." << endl; // welcome message
cout << "Please inter the sequence number in the form of an integer." << endl;
cin >> seqNum; // user input
while ( seqNum < 0) // validation, number must be positive
{
cout << "Please enter a positive number." << endl;
cin >> seqNum;
} // end while
if (seqNum > 0)
{
for ( long int i = 0; i < seqNum; i++ )
{
val = val + 4*(pow(-1.00,i)/(1 + 2*i)); // Gregory-Leibniz sum calculation
}// end for
cout << val;
} // end if
return 0;
}
任何帮助将不胜感激。谢谢
【问题讨论】:
-
一个典型的
long double只能表示大约 35 位有效数字的值。例如,IEEE754 四精度浮点——这是long double非常常用的格式——只保证最多 34 位有效数字。这意味着对于 pi 的小数点后 42 位的要求在大多数实际实现中是无法实现的。此外,在您的代码中,val未初始化,第一次使用会访问其值 - 这会产生未定义的行为。 -
我明白了,所以即使我使用 setprecision(42),第 35 位之后的任何内容都会是 goop?另外,我不确定我的 val 未初始化是什么意思。我以为我在顶部这样做是通过声明它是一个长的双倍
-
定义
long double val表示val已定义但未初始化。访问未初始化变量的值会产生未定义的行为。val在嵌套循环中的第一次用法是val = val + 4*(pow(-1.00,i)/(1 + 2*i));,这意味着val的新值是使用其先前值计算的 - 所以第一次发生时,val未初始化,并且行为未定义。并且(这是您所做的一个常见但有缺陷的假设)long double val不需要将val初始化为零或任何其他特定值。 -
@Peter long double 通常不是 IEEE754 四倍精度,而是 x86 上的 80 位扩展精度
-
pow(-1.00,i)是一种获取交替符号的效率极低的方法。只需使用类似i % 2 == 0 ? 1 : -1