Ошибка SegFault при вычислении квадрата root (метод Ньютона) - PullRequest
1 голос
/ 29 января 2020

Я очень плохо знаком с C ++, но я знаю, что существует множество способов получить ошибку SegFault, но я не уверен, почему я получаю ее здесь. Цель программы - вычислить квадрат root числа, используя метод Ньютона. Я предполагаю, что это как-то связано с рекурсией, но я уверен, что код будет работать в Java.

#include <iostream>
#include <sstream>

using namespace std;

double sqrt(double eps, double num, double last_guess)
{

    if(num == 0 || num == 1)
    {
        return num;
    }

    int next = (num + (num/last_guess)) / 2;

    if(abs(last_guess - next) <= eps)
        return next;
    else
        return sqrt(eps, num, next);
}

int main(int argc, char *argv[]) {
    double eps, num;
    istringstream iss; //input string

    if(argc == 3)
    {
        iss.str(argv[1]);
        if ( !(iss >> eps) ) {
            cerr << "Error: The first argument is not a valid double." << endl;
            return 1;
        }

        iss.clear();

        iss.str(argv[2]);
        if ( !(iss >> num) ) {
            cerr << "Error: The second argument is not a valid double." << endl;
            return 1;
        }

    } else if(argc == 2) {
        iss.str(argv[1]);
        if ( !(iss >> num) ) {
            cerr << "Error: Argument is not a valid double." << endl;
            return 1;
        }

        eps = 0.000001;
    }

    cout << "sqrt(" << eps << ", " << num << ") = " << sqrt(eps,num, num) << endl;
    return 0;
}

Пример ввода: 0.000001 4.0

1 Ответ

1 голос
/ 30 января 2020

Запуск вашей программы под GDB показывает, что она находится в бесконечной рекурсии:

(gdb) run
Starting program: /tmp/a.out 0.000001 4.0

Program received signal SIGSEGV, Segmentation fault.
0x000055555555522d in sqrt (eps=<error reading variable: Cannot access memory at address 0x7fffff7feff8>, 
    num=<error reading variable: Cannot access memory at address 0x7fffff7feff0>, last_guess=<error reading variable: Cannot access memory at address 0x7fffff7fefe8>) at foo.cc:7
7       {
(gdb) bt 20
#0  0x000055555555522d in sqrt (eps=<error reading variable: Cannot access memory at address 0x7fffff7feff8>, 
    num=<error reading variable: Cannot access memory at address 0x7fffff7feff0>, last_guess=<error reading variable: Cannot access memory at address 0x7fffff7fefe8>) at foo.cc:7
#1  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#2  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#3  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#4  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#5  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#6  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#7  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#8  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#9  0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#10 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#11 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#12 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#13 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#14 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#15 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#16 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#17 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
#18 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=2) at foo.cc:19
#19 0x00005555555552df in sqrt (eps=9.9999999999999995e-07, num=4, last_guess=3) at foo.cc:19
(More stack frames follow...)
  1. Нет причин делать вашу процедуру рекурсивной.
  2. Ваш алгоритм не работает признать (пропускает проверку), что вы уже вычислили правильный ответ.

    Не следует сравнивать дельту между вашими догадками с эпсилоном. Вместо этого вы должны сравнить дельту между вашим вычисленным ответом и реальным ответом.

  3. Как отметил @ PaulMcKenz ie, вы не должны хранить свои последовательные приближения в целых числах (используйте double вместо).

  4. Чтобы исправить программу, вам нужно использовать правильную формулу для следующего предположения:

    double next = (last_guess + (num/last_guess)) / 2;
...