-21 / 3 / 0
Регистрация: 01.09.2017
Сообщений: 21
1

Логическая ошибка при рекурсии

29.03.2018, 19:48. Показов 1141. Ответов 6
Метки нет (Все метки)

Решил задачу в теме про рекурсию. Использован алгоритм Евклида. Условие:
Напишите рекурсивную функцию вычисления наибольшего общего делителя двух положительных целых чисел (Greatest Common Divisor, GCD). Для этого воспользуйтесь следующими свойствами. Требования к реализации: в данном задании запрещено пользоваться циклами. Вы можете заводить любые вспомогательные функции, если они вам нужны.

Проблема в том, что мой рекурсивный алгоритм в функции, которая вызывает себя, работает корректно ровно до последней итерации(когда одно из значений становится равно 0). А конкретно часть (a = m) и (b = m) попросту игнорируется. И дело даже не в проверке на равенство нулю перед алгоритмом, потому что когда управление передаётся строке 9, условия как раз выполняются. Я проверял, убирал проверку. Вывод в строке 10 добавлен только чтобы показать какие значения принимают аргументы функции на каждом этапе итерации. По логике вещей значение b в последней итерации должно было ровняться 0. Следовательно возвращать я должен бы то значение, которое больше, а не то которое меньше. Почему так происходит? Где ошибка?

Мой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <conio.h>
 
unsigned gcd(unsigned a, unsigned b)
{
    unsigned m = 0;
    if ((a != 0) && (b != 0))
    {
    (a > b) ? ((m = a % b) && (a = m)) : ((m = b % a) && (b = m)); 
    std::cout << "a = " << a << "\n" << "b = " << b << "\n\n";
    }
    else return a + b;
 
    if (m!=0) gcd(a, b);
    else if (a > b) return b; else return a;
}
 
int main()
{   
    std::cout<<gcd(18, 462); //значения чисто для примера
    _getch();
    return 0;
}
Миниатюры
Логическая ошибка при рекурсии  
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.03.2018, 19:48
Ответы с готовыми решениями:

Логическая ошибка: при делении результат всегда единица
Ошибка заключается в том что в переменную L должен идти остаток деления L на 10, но почему то...

Логическая ошибка
Вот фрагмент int main() { using namespace std; int x = 1; double eps = 0.25;...

логическая ошибка!!
1. Описать структуру с именем PRICE, содержащую следующие поля: - название товара; - название...

Неведомая логическая ошибка (С++)
Здравствуйте. Хочу написать программу, которая умела бы считать значение выражения (a + b)^n при...

6
473 / 425 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
29.03.2018, 20:00 2
Цитата Сообщение от FeewrE Посмотреть сообщение
if ((a != 0) && (b != 0))
Цитата Сообщение от FeewrE Посмотреть сообщение
else return a + b;
Ну если b = 0, то при проверке условия, мы выйдем в else, и выведем a+b, в твоем случае 0+6 = 6
0
-21 / 3 / 0
Регистрация: 01.09.2017
Сообщений: 21
30.03.2018, 15:06  [ТС] 3
Уважаемые знатоки, повторяю ещё раз. Проверка тут не при чём. Для примера, скомпилируйте код без строк 7 и 12, вывод не изменится, если не использовать как аргумент 0, разумеется(тогда программа крашится, потому что происходит деление на 0 в алгоритме). Если вы не знаете, просто не сталкивались с подобной ошибкой, или вам лень думать, то пожалуйста не отвечайте в этой теме

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <conio.h>
 
unsigned gcd(unsigned a, unsigned b)
{
    unsigned m = 0;
    //if ((a != 0) && (b != 0))
    {
    (a > b) ? ((m = a % b) && (a = m)) : ((m = b % a) && (b = m)); 
    std::cout << "a = " << a << "\n" << "b = " << b << "\n\n";
    }
    //else return a + b;
 
    if (m!=0) gcd(a, b);
    else if (a > b) return b; else return a;
}
 
int main()
{   
    std::cout<<gcd(18, 462); //значения чисто для примера
    _getch();
    return 0;
}
Добавлено через 13 минут
Мы не выйдем в else по той простой причине, что в последнем вызове функции gcd m будет равно 0 и вместо очередного вызова функции gcd она вернёт значение в вызывающую функцию gcd, а та в предыдущую, и так далее пока первая вызванная gcd не вернёт значение в main, а та выведет его на экран
0
652 / 456 / 212
Регистрация: 06.09.2013
Сообщений: 1,253
30.03.2018, 15:12 4
FeewrE, а зачем вы такую, извините, ерунду пишете
(a > b) ? ((m = a % b) && (a = m)) : ((m = b % a) && (b = m));
возможно, у вас он вычисляет первый операнд логического И, он - ноль, второй считать не надо, оптимизация, однако.
Кто вас научил так писать? Пишите обычный if.
0
473 / 425 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
30.03.2018, 15:19 5
Цитата Сообщение от FeewrE Посмотреть сообщение
Если вы не знаете, просто не сталкивались с подобной ошибкой
Конечно не сталкивались, код то твой.
Цитата Сообщение от FeewrE Посмотреть сообщение
или вам лень думать, то пожалуйста не отвечайте в этой теме
Преобразуйте тернарный оператор в условный, так легче дебажить. В последний момент b не присваивало значение m.
По правде говоря, сама конструкция такого присвоения весьма чудная.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
unsigned gcd(unsigned a, unsigned b)
{
    unsigned m = 0;
    if (a && b)
    {
        if (a > b)
        {
            m = a % b;
            a = m;
        }
        else
        {
            m = b % a;
            b = m;
        }
        std::cout << "a = " << a << "\n" << "b = " << b << "\n\n";
    }
 
    if (m != 0) 
        gcd(a, b);
    else if (a > b) 
        return b;
    else
        return a;
}
0
1269 / 1026 / 470
Регистрация: 25.12.2016
Сообщений: 3,333
30.03.2018, 15:22 6
Лучший ответ Сообщение было отмечено FeewrE как решение

Решение

Цитата Сообщение от FeewrE Посмотреть сообщение
if (m!=0) gcd(a, b);
Функция вызывается, а возвращаемое значение не используется. Логическая ошибка, однака.
0
473 / 425 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
30.03.2018, 15:27 7
likehood, да, причем если нормально писать возвращение из рекурсии, в какой-то момент всплывает

Добавлено через 3 минуты
А вообще, используйте нормальную версию рекурсивной функции, или расширенную (двоичный вариант).
C++
1
2
3
4
5
6
7
int gcd(int a, int b) 
{
    if (b == 0)
        return a;
 
    return gcd(b, a % b);
}
И почему Вам нужен 0 - не ясно, ведь ищется НОД
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.03.2018, 15:27
Помогаю со студенческими работами здесь

Логическая ошибка в цикле for
Привет всем! Написал небольшую программу для изучения цикла for. Проблема в том, что все...

Логическая ошибка в консольном приложении
На рисунке изображен результат выполнения программы, которая должна определять, не превышен ли...

Ошибка в рекурсии
почему то переменная y не меняется во время рекурсии. что за? #include &lt;iostream&gt; using...

Ошибка в Рекурсии с++
Здравствуйте,у меня в данном коде выбивает ошибку в строке 23 .В рекурсии я не силён и прошу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru