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

问题描述 投票:-2回答:3

我想用这个问题来改进我对计算机工作原理的一般理解,因为我可能永远都没有机会深入而深刻地学习。提前抱歉,如果这个问题很愚蠢,一般没用,但我更喜欢这样学习。

我正在学习c ++,我在网上找到了一个实现Newton-Raphson方法的代码,用于查找函数的根。代码非常简单,正如你可以从中看到的那样,一开始它要求所需的容差,如果我给出一个“正常”的数字,它就能正常工作。相反,如果它要求容差我写的像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;
}
c++ numerical-methods arbitrary-precision
3个回答
3
投票

1e-600不能代表大多数double的实现。 std::cin将无法将您的输入转换为double并陷入失败状态。这意味着,除非您清除错误状态,否则任何未来的std::cin也会在不等待用户输入的情况下自动失败。

来自cppreference(自c ++ 17以来):

如果提取失败,则将零写入值并设置failbit。如果提取导致值太大或太小而无法拟合值,则会写入std::numeric_limits<T>::max()std::numeric_limits<T>::min()并设置failbit标志。


1
投票

如上所述,1e-600不是有效的double值。但是,除了超出范围之外,还有更多内容。可能发生的是1扫描到tol,然后e-600的一部分被扫描到pnew,这就是为什么它立即结束,而不是要求输入pnew


0
投票

就像François所说的那样,当你使用64位机器(具有相应的操作系统)和32位机器上的2 ^ 32时,你不能执行2 ^ 64,你可以使用SSE,这是用于浮点表示的4个32字节数据。在你的程序中,函数在每次迭代时都会失败并用“if”跳过你的测试,因此在结束循环之前永远不会返回。

© www.soinside.com 2019 - 2024. All rights reserved.