为什么程序甚至在 运行 之前就结束了?

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。