2017-02-16 9 views
1

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

У меня проблемы с петлей. Когда я прошу квадратный корень из 67, он находит его, но он трижды повторяет правильный ответ.

Enter a value to be square rooted: 
67 
33.5 
guess = 17.75 
guess = 10.7623 
guess = 8.49387 
guess = 8.19096 
guess = 8.18535 
guess = 8.18535 
guess = 8.18535 
The program took 7 guess to find an estimation. 

Когда я пытаюсь найти квадратный корень из 5 он находит ее, но продолжает петлю на неопределенный срок

using namespace std; 

int main() 
{ 
double guess2; 
double squarenumber; 
double guess1; 
int numofguess = 0; 

cout << "Enter a value to be square rooted: " << endl; 
cin >> squarenumber; 
guess1 = squarenumber/2; 
cout << guess1 << endl; 

do 
{ 

guess2 = (guess1 - (((guess1 * guess1) - squarenumber)/(2* guess1))); 
guess1 = guess2; 

cout << "guess = " << guess2 << endl; 

numofguess = numofguess + 1; 

} while ((guess2 * guess2) > squarenumber); 

cout<< "The program took "<< numofguess <<" guess to find an estimation."; 

return 0; 
} 
+5

Что вы наблюдали , а через свой код, по очереди, в отладчике? –

+1

Попробуйте напечатать 'guess2 * guess2' каждый раз через цикл. Обязательно распечатайте его с большим количеством цифр точности. – Barmar

+3

Двойной держит более 6 десятичных цифр, поэтому, возможно, разница в цифрах, которые вы не видите. Проверьте это сообщение [Является ли математика с плавающей запятой?] (Http://stackoverflow.com/questions/588004/is-floating-point-math-broken) –

ответ

1

Я думаю, что вам не хватает является надлежащее состояние выхода. Ваш код записывается в цикл до бесконечности, пока предположение не будет «идеальным». У вас должно быть условие завершения, если текущее предположение совпадает с предыдущим догадком, что, очевидно, означает, что вы не будете лучше. Вот мое предложение основано на коде: ответ

using namespace std; 

int main() 
{ 
double guess2; 
double squarenumber; 
double guess1; 
int numofguess = 0; 

cout << "Enter a value to be square rooted: " << endl; 
cin >> squarenumber; 
guess2 = guess1 = squarenumber/2; 
cout << guess1 << endl; 

const double epsilon = squarenumber * 1E-6; 
do 
{ 
guess1 = guess2; 
guess2 = (guess1 - (((guess1 * guess1) - squarenumber)/(2* guess1))); 


cout << "guess = " << guess2 << endl; 

numofguess = numofguess + 1; 

} while ((guess2 * guess2) > squarenumber && fabs(guess2-guess1) > epsilon); 

cout<< "The program took "<< numofguess <<" guess to find an estimation."; 

return 0; 
} 
+0

, это не будет работать, потому что после строки 'guess1 = guess2;', 'fabs (guess2-guess1)' всегда равна нулю – user31264

+0

Вы правы ... Я отредактировал код, чтобы исправить эту глупую ошибку. –

+0

Я бы использовал 'if (fabs (...) user31264

0

Микаэля С. Гимарайнш является в основном правильно, проверьте наличие значения episolon (абсолютная разница от правильного ответа и вашего ответа). Но «(guess2 * guess2)> squarenumber» следует полностью отбросить. Это потому, что значение может теоретически перерегулироваться и быть слишком низким. Алгоритм идет вверх, если значение слишком низкое. например если вы хотите SQRT (25) и ваш «guess1» предсказание слишком низко на 2, то guess2 будет равна

(2 - (((2 * 2) - 25)/(2* 2))) = 7.25; 

А на следующей итерации затем падает до 6.725624, поэтому головы в правильном направлении. Низкие значения фактически повышаются и в конечном итоге приближаются к цели. Если остановиться, если значение падает ниже истинного SQRT, тогда вы можете получить «ложные срабатывания», когда слишком низкие значения принимаются как достаточно точные.

Время, когда система «застряла», в основном напоминала историю Acchiles и Tortoise. На каждом шаге система делят оставшееся расстояние на какую-то величину, но изменение было поэтому меньшим на каждом шагу и теоретически никогда не сходилось с точным значением, поэтому вы решаете, сколько точности вы хотите, чтобы оно заканчивалось в заданное время.

Кроме того, проблема, с которой система, похоже, предпринимает слишком много шагов для схождения, состоит в том, что числа с плавающей запятой хранятся в более высокой точности, но cout имеет ограниченную точность отображения. Вы можете контролировать, что, посылая настройки значения COUT перед командами печати:

std::cout << std::fixed; // force all values to show to the same decimals 
std::cout << std::setprecision(6); // set how many places to show 

Этого код может передаваться COUT в одной команде, прежде чем значение для печати, а также:

std::cout << std::fixed << std::setprecision(6) << "guess = " << guess2 << endl;