2016-11-19 2 views
1

Моя квадратная корневая программа по какой-то причине получает ответ, который немного отличается от того, что он должен получить для большинства входных данных. Я не знаю, почему это так. Только определенные входы неверны. Я также получаю ошибку сегментации на том самом конце после ответа, и я не уверен, почему это так.C++ Квадратный корень с рекурсией

#include<iostream> 
#include<cmath> 
#include<cfloat> 
#include<string> 
#include <cstdlib> 
using namespace std; 

//declare sqroot function calls recursive function newton 
double sqroot1(double num); 
double newton(double num, double guess); 
int main(int argc, char **argv) 
{ 

    for(int i = 0 ; i < argc ; i++) 
    { 
     cout<<"sqroot("<<argv[i+1]<<") is "<< sqroot1(atoi(argv[i+1]))  <<endl; 
    } 
} 

double newton(double num, double a) 
{ 
    if ((abs(a*a - num) <= FLT_EPSILON)) 
    { 
     return a; 
    } 
    else 
    { 
     newton(num, (a+num/a)/2); 
    } 
} 

double sqroot1(double num) 
{ 
    double sqrt = newton(num,num/2); 
    return sqrt; 
} 
+0

Включите все предупреждения и посмотрите, что говорит вам компилятор. И см. [Почему «использование пространства имен std» считается плохой практикой?] (Http://stackoverflow.com/q/1452721/995714) –

+0

Каковы некоторые значения, которые дают плохие квадратные корни и какие значения вы получаете за них? – 1201ProgramAlarm

ответ

2

Функция имеет неопределенное поведение, потому что вы забыли поместить оператор возврата

double newton(double num, double a) 
{ 


    if ((abs(a*a - num) <= FLT_EPSILON)) 
    { 
     return a; 
    } 
    else 
    { 
     newton(num, (a+num/a)/2); 
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    } 


} 

должно быть

return newton(num, (a+num/a)/2); 
1

Вы получаете сбой, потому что вы пытаетесь получить доступ к argv[argc], который находится в конце массива argv.

Ваши номера, скорее всего, отключены, потому что вы сравниваете FLT_EPSILON, что соответствует значениям float. DBL_EPSILON используется для парных разрядов. Тем не менее, сравнение с любым из них не является правильным подходом к этой проблеме. Вам нужно проверить разницу, которая масштабируется относительно вашего значения a.

0

Я вижу две основные ошибки, которые должны быть закреплены первым:

  1. Ваша главная функция не имеет возврата. Вы должны разместить return 0; в конце своей основной функции до последнего }.

  2. Вы пытаетесь получить доступ к argv[argc], которого не существует. Последний существующий элемент в этом массиве - argv[argc - 1]. Попробуйте изменить оператор цикла, чтобы он не пытался читать в этой несуществующей части массива.

0

Добавление к ответе 1201ProgramAlarm, почему так плохо?

if ((abs(a*a - num) <= eps)) 

Скажем САП 1e-15, немного больше, чем DBL_EPSILON. Ну, если a даже умеренно большой (что-то вроде 5 или больше), то устройство на последнем месте (ulp) a*a больше, чем eps, и это условие может быть истинным, только если a*a == num. Существует риск, с округлением, что это не будет достигнуто, и вы закончите бесконечную рекурсию и крушение.

Теперь давайте скажем, что num очень мало, что для первоначального предположения

abs(num/2*num/2 - num) <= eps 

Так, например, sqroot1 (1e-20) будет оценивать

abs(1e-40/4 - 1e-20) <= 1e-15 

, которое истинно, и вы будете получить 5e-21 в качестве квадратного корня из 1e-20. Это ужасная точность.

Смежные вопросы