为什么程序甚至在 运行 之前就结束了?
Why does the program ends even before running?
我想借这个问题来提高我对计算机工作原理的一般理解,因为我可能永远没有机会深入研究。如果这个问题很愚蠢并且一般来说没有用,请提前道歉,但我更喜欢以这种方式学习。
我正在学习c++,我在网上找到了一个实现Newton-Raphson方法求函数根的代码。代码非常简单,从中可以看出,一开始它要求提供所需的公差,如果我给出 "decent" 数字,它就可以正常工作。相反,当它要求容差时,我写了类似 1e-600
的东西,程序立即崩溃,输出为 Enter starting value x: Failed to converge after 100 iterations
。
收敛失败的输出应该是 运行 循环超过 100 次迭代的结果,但情况并非如此,因为循环甚至没有开始。看起来程序已经知道它不会达到那个容忍度。
为什么会这样?即使程序没有尝试循环 100 次,它怎么能写出那个输出呢?
编辑: 似乎我写的所有内容都毫无意义(太小的数字,单词)当它要求容差时会产生 pnew=0.25 然后代码运行 100 次并失败.
代码如下:
#include <iostream>
#include <cmath>
using namespace std;
#define N 100 // Maximum number of iterations
int main() {
double p, pnew;
double f, dfdx;
double tol;
int i;
cout << "Enter tolerance: ";
cin >> tol;
cout << "Enter starting value x: ";
cin >> pnew;
// Main Loop
for(i=0; i < N; i++){
p = pnew;
//Evaluate the function and its derivative
f = 4*p - cos(p);
dfdx= 4 + sin(p);
// The Newton-Raphson step
pnew = p - f/dfdx;
// Check for convergence and quit if done
if(abs(p-pnew) < tol){
cout << "Root is " << pnew << " to within " << tol << "\n";
return 0;
}
}
// We reach this point only if the iteration failed to converge
cerr << "Failed to converge after " << N << " iterations.\n";
return 1;
}
如前所述,1e-600
不是有效的 double
值。然而,除了超出范围之外,还有更多的原因。可能发生的情况是 1 被扫描到 tol
,然后 e-600
的某些部分被扫描到 pnew
,这就是为什么它立即结束,而不是要求输入 pnew
.
1e-600
不能用 double
的大多数实现来表示。 std::cin
将无法将您的输入转换为 double
并陷入失败状态。这意味着,除非您清除错误状态,否则任何未来 std::cin
也会自动失败,而无需等待用户输入。
来自 cppreference(自 c++17 起):
If extraction fails, zero is written to value and failbit
is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max()
or std::numeric_limits<T>::min()
is written and failbit
flag is set.
就像François说的,你不能在64位机器上执行2^64(对应OS),在32位机器上不能执行2^32,你可以使用SSE,这是4个32字节的数据用于浮点表示。在您的程序中,该函数在每次迭代时都会失败,并使用 "if" 跳过您的测试,因此在结束循环之前永远不会 returns。
我想借这个问题来提高我对计算机工作原理的一般理解,因为我可能永远没有机会深入研究。如果这个问题很愚蠢并且一般来说没有用,请提前道歉,但我更喜欢以这种方式学习。
我正在学习c++,我在网上找到了一个实现Newton-Raphson方法求函数根的代码。代码非常简单,从中可以看出,一开始它要求提供所需的公差,如果我给出 "decent" 数字,它就可以正常工作。相反,当它要求容差时,我写了类似 1e-600
的东西,程序立即崩溃,输出为 Enter starting value x: Failed to converge after 100 iterations
。
收敛失败的输出应该是 运行 循环超过 100 次迭代的结果,但情况并非如此,因为循环甚至没有开始。看起来程序已经知道它不会达到那个容忍度。
为什么会这样?即使程序没有尝试循环 100 次,它怎么能写出那个输出呢?
编辑: 似乎我写的所有内容都毫无意义(太小的数字,单词)当它要求容差时会产生 pnew=0.25 然后代码运行 100 次并失败.
代码如下:
#include <iostream>
#include <cmath>
using namespace std;
#define N 100 // Maximum number of iterations
int main() {
double p, pnew;
double f, dfdx;
double tol;
int i;
cout << "Enter tolerance: ";
cin >> tol;
cout << "Enter starting value x: ";
cin >> pnew;
// Main Loop
for(i=0; i < N; i++){
p = pnew;
//Evaluate the function and its derivative
f = 4*p - cos(p);
dfdx= 4 + sin(p);
// The Newton-Raphson step
pnew = p - f/dfdx;
// Check for convergence and quit if done
if(abs(p-pnew) < tol){
cout << "Root is " << pnew << " to within " << tol << "\n";
return 0;
}
}
// We reach this point only if the iteration failed to converge
cerr << "Failed to converge after " << N << " iterations.\n";
return 1;
}
如前所述,1e-600
不是有效的 double
值。然而,除了超出范围之外,还有更多的原因。可能发生的情况是 1 被扫描到 tol
,然后 e-600
的某些部分被扫描到 pnew
,这就是为什么它立即结束,而不是要求输入 pnew
.
1e-600
不能用 double
的大多数实现来表示。 std::cin
将无法将您的输入转换为 double
并陷入失败状态。这意味着,除非您清除错误状态,否则任何未来 std::cin
也会自动失败,而无需等待用户输入。
来自 cppreference(自 c++17 起):
If extraction fails, zero is written to value and
failbit
is set. If extraction results in the value too large or too small to fit in value,std::numeric_limits<T>::max()
orstd::numeric_limits<T>::min()
is written andfailbit
flag is set.
就像François说的,你不能在64位机器上执行2^64(对应OS),在32位机器上不能执行2^32,你可以使用SSE,这是4个32字节的数据用于浮点表示。在您的程序中,该函数在每次迭代时都会失败,并使用 "if" 跳过您的测试,因此在结束循环之前永远不会 returns。