Помощь - Поиск - Пользователи - Календарь
Полная версия: Найти наибольший общий делитель всех элементов массива
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Shmanich
Помогите найти ошибку в коде.


#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#define N 5
int main()
{ /* int mass[N]; */
int mass[N]={2, 4, 8, 16, 32}; // Объявляем массив.
int i, g, h, x, temp, NOD;
/* srand(unsigned(time(NULL))); // Запуск генератора случайных чисел. */
printf("\n Massiv iz 5 elementov: \n");
for(i=0; i<N; i++)
{
/* mass[i]=rand()%10+1; */
printf("\n Mass[%d] = %d. ", i, mass[i]);
}

if(mass[0]<mass[i]) // Если первый элемент массива меньше второго, тогда...
{ g=mass[i]; h=mass[0]; } // запомининаем след. элемент в перем-ой g, а первый в перем-ой h.
if(mass[0]>mass[i]) // Если первый элемент массива больше второго, тогда...
{ g=mass[0]; h=mass[i]; } // запомининаем первый элемент в перем-ой g, а след. в перем-ой h.

do // выполнять до тех пор...
{
if(g%h == 0) // если большее число делится на меньшее без остатка, тогда...
{ NOD=h; } // меньшее число и есть НОД.
else // Иначе.
{ temp=h;
h=g%h; // Второе станет остатком от деления.
g=temp; // А первое число вторым, значения которого записываем во временную переменную.
NOD=h; } // Пока НОДом будет второе число.
}
while(g%h!=0); // ...пока остаток от деления g и h элементов не перестанет быть равным 0.

if (NOD != 1) // Если НОД не равен 1...
{ printf("\n \n NOD = %d. \n", NOD); } // Выводим результат на экран.
else
{ printf("\n \n Chisla ne imeut obschih deliteley \n"); } // Числа не имеют общих делителей.

getch();
return 0;
}




Программа выдает, что общих делителей не найдено, хотя здесь НОД = 2.
Генератор случайных чисел временно отключил, чтобы проверить программу на конкретных числах.

Интересно, что когда я уменьшаю массив до 3 элементов и ввожу 2, 4, 8, то НОД находится верно (НОД=2).
Shmanich
У кого-неибудь есть какие-нибудь мысли?
IUnknown
Debugger + пошаговый проход по программе тебе помогут найти ошибку. Второй раз помогать чтоб ты потом опять начал "править" чужое решение, причем не разобравшись в нем - желающих нет.
Shmanich
Цитата(IUnknown @ 30.05.2012 23:59) *

Debugger + пошаговый проход по программе тебе помогут найти ошибку. Второй раз помогать чтоб ты потом опять начал "править" чужое решение, причем не разобравшись в нем - желающих нет.


Твой код не содержал одну проверку, я пытался ее добавить. Твой код целиком и полностью я менять не собирался, но затем мне предложили другой вариант решения, который мне показался интереснее. Признайся просто что не знаешь где ошибка в коде и все, зачем обязательно хохлиться?
-Федосеев Павел-
Цитата
Признайся просто что не знаешь где ошибка в коде и все, зачем обязательно хохлиться?

Прикольно!
Ты пытаешься взять "на слабо" вместо того, чтобы научиться пользоваться инструментом - пошаговым выполнением с наблюдением за состоянием переменных.
Krjuger
Поверь,человек, которого ты пытаешся взять "на слабо" уже не первый год программирует и не на одном языке.
Твоя задача не является чем то сверх трудным,более того я бы сказал она банальна.
Здесь никто не обязан помогать вам, а вы еще и что то требуете.
Shmanich
Цитата(Krjuger @ 31.05.2012 16:52) *

Поверь,человек, которого ты пытаешся взять "на слабо" уже не первый год программирует и не на одном языке.
Твоя задача не является чем то сверх трудным,более того я бы сказал она банальна.
Здесь никто не обязан помогать вам, а вы еще и что то требуете.


Я этого человека не знаю и не могу сказать какой он в жизни профи, я лишь вижу, что он ничего конкретного по теме не сказал. Свою версию кода не привел и новичка в ошибку в коде мордой не тыкнул.

Зачем вообще создан этот раздел форума, если не решать поставленые задачи? Чтобы супер-пупер-гуру в С++ в очередной раз показывали, что они на столько круты, что им лень лень написать две, три строки кода? Тем более когда задача такая банальная.
Игорь
Кстати, программа твоя работает, вроде бы, правильно (правда не могу понять как именно). Код я немножко поправлял, но ничего серьёзного, так что перепроверь ещё раз.


#include <stdio.h>

#define N 5

int main() {

int mass[N] = {2, 4, 8, 16, 32};
int i, g, h, x, temp, NOD;


if(mass[0] < mass[N-1]) {
g = mass[N-1];
h = mass[0];
}

if(mass[0] > mass[N-1]) {
g = mass[0];
h = mass[N-1];
}

do {
if(g%h == 0)
NOD=h;
else {
temp = h;
h = g % h;
g = temp;
NOD = h;
}
}
while(g%h != 0);

printf("NOD: %d\n", NOD);

return 0;

}

Shmanich
Игорь, твой код тоже не работает, ошибка в цикле do while! sad.gif
Krjuger
Форум создан,чтобы помогать учиться, а не делать все за других.Хотите, чтобы вам сделали, все что захотите и при этом не прилагая никаких усилий, идите к фрилансерам, они вам за денежку все что угодно сделают.
Тебя уже несколько раз "мордой тыкали" в других темах, но результатов это не приносило. Со временем о любом человеке складывается определенное мнение. О вас складывается мнение, что вы считаете здесь всех обязанными вам помогать.Я вам давал наводки,как можно исправить вашу задачу, вы оставались глухи.

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

И чтобы внести ясность,программа, по хорошему, должна считать для любых наборов элементов,а не в строго упорядоченном виде,поэтому

if(mass[0] < mass[N-1]) {
g = mass[N-1];
h = mass[0];
}

if(mass[0] > mass[N-1]) {
g = mass[0];
h = mass[N-1];
}


Просто ужас какой то.А что произойдет, если mass[0] = mass[N-1] ???????
А ничего, что НОД ищется только для двух элементов????? для первого и последнего, а никак не для всех элементов массива.Вы взяли откуда то код, прикрутили массив и теперь кричите,что у вас не работает.То что вы скинули воообще не решает вашу задачу.
Игорь
Цитата
Игорь, твой код тоже не работает, ошибка в цикле do while!

Ты уж извини, но это твой код (цикл по крайней мере).
А вот код, который прокомментировал Krjuger, мой.

Вообще могу предложить найти минимальный эллемент массива и с ним работать.
Shmanich
Krjuger, учится говоришь? Так для этого существуют учебники и задачники по С++. Зачем тогда этот форум?
Если я молчу на ваши наводки, это не значит что я не думаю и не ищу нужное решение. Пока вы тут пальцы от клаву терли, чтобы продемонстрировать, какой вы тут сУрьезный дядечка я сообразил одно такое. cool.gif Может криво, но зато работает.

const int N = 5; // Размер массива.
int main()
{
int mass[N]={8, 16, 64, 32, 7};
int NOD, i, flag;
printf("\n Massiv iz 5 elementov \n");
for(i=0; i<N; i++)
{
printf("\n Mass[%d] = %d ", i, mass[i]);
}
NOD = mass[0]; // Предпологаем, что первый элемент массива - это НОД.
for(i=1; i<N; i++)
if(NOD > mass[i]) // Если предполгаемый НОД больше след. элемент массива,
{ NOD = mass[i]; } // тогда след.элемент - НОД.
flag=1; // Флаг на true
while(flag==1) // Пока флаг = true делаем.
{
flag=0; // Флаг = false.
for(i=0; i<N; i++)
if(mass[i]%NOD!=0) // Если след. элемент массива делится на предпологаемый НОД без остатка,
{ flag=1; } // тогда ставим флаг на true.
NOD--; // Здесь уменьшаем значение НОД.
}
NOD++; // Здесь увеличиваем значение НОД.
printf("\n \n NOD = %d. \n", NOD);

getch();
return 0;
}



Думаю, как прикрутить генератор случайных чисел догадаетесь сами, раз такие умные. dry.gif
Krjuger
Ну чтож, это уже похоже на правду, но есть один маленький недочет.
Сделайте,чтобы работало с отрицательными числами)А то как то непорядочно получается
Shmanich
Цитата(Krjuger @ 31.05.2012 22:23) *

Ну чтож, это уже похоже на правду, но есть один маленький недочет.
Сделайте,чтобы работало с отрицательными числами)А то как то непорядочно получается


Пока что не нашел как это можно сделать, но добавил проверку.

for(i=0; i<N; i++)
{
if ((mass[i]<0) || (mass[i]==0)) // Если в массиве найден элемент <=0...
{ printf("\n \n Oshibka! V massive nayden element <= 0."); // Вывести сообщение об ошибке.
break; } // Остановить цикл.
else
if (mass[i]%NOD!=0) // Если след. элемент массива делится на предпологаемый НОД без остатка,
{ flag=1; } // тогда ставим флаг на true.
NOD--; // Здесь уменьшаем значение НОД.
}

...

if ((NOD<0) || (NOD==0)) // Если НОД <=0...
{ printf("\n \n Chisla ne imeut obshih deliteley.\n"); } // числа не имеют общих делителей.
else // Иначе
{ printf("\n \n NOD = %d. \n", NOD); } // Выводим знначние НОД.



Однако, проверка не работает, если 0 выпадат дальше 1-ой позиции в массиве sad.gif. Почему? Думаю!
Krjuger
Что за такое страшное условие.Прям в дрож бросает.
if ((mass[i]<0) || (mass[i]==0))

Можно записать,как
if (mass[i]<=0) 

Затем ты его явно не туда вставил,еесли ты хочешь,чтобы выводилось сообщение об ошибке,то надо вставлять сразу после начала первого цикла.

NOD = mass[0]; // Предпологаем, что первый элемент массива - это НОД.
for(i=1; i<N; i++)
if (mass[i]<=0)
{ printf("\n \n Oshibka! V massive nayden element <= 0."); // Вывести сообщение об ошибке.
break; } // Остановить цикл.
else
{
if(NOD > mass[i]) // Если предполгаемый НОД больше след. элемент массива,
{ NOD = mass[i]; } // тогда след.элемент - НОД.
flag=1; // Флаг на true
while(flag==1) // Пока флаг = true делаем.
{
flag=0; // Флаг = false.
for(i=0; i<N; i++)
if(mass[i]%NOD!=0) // Если след. элемент массива делится на предпологаемый НОД без остатка,
{ flag=1; } // тогда ставим флаг на true.
NOD--; // Здесь уменьшаем значение НОД.
}
NOD++; // Здесь увеличиваем значение НОД.
printf("\n \n NOD = %d. \n", NOD);
}

Федосеев Павел
Я бы реализовал всю программу следующим образом:
а) вынес расчёт НОД (GCD) в функцию
б) последовательно обращался к этой функции
int GCD(int a, int b) - не я придумал - честно "тиснул" из "http://e-maxx.ru/algo/euclid_algorithm"
{
int tmp;

while(b)
{
a%=b;
tmp=a; a=b; b=tmp; /*swap(a, b);*/
}
return a;
}

int main()
{
...................................................
NOD=mass[0];
for(i=1; i<N; i++)
{
NOD=GCD(NOD, mass[i]);
}
...............................................
}
Shmanich
Krjuger, твоя проверка на фурычит. А вот решение Павла довольно интересна smile.gif, спасибо.
Krjuger
Да,я закрывающую скобку не туда поставил.Да и вообще с еще 1 флагом проще.

minus=false;
NOD = mass[0]; // Предпологаем, что первый элемент массива - это НОД.
for(i=1; i<N; i++)
if (mass[i]<=0)
{ minus=true;
break; } // Остановить цикл.
else
{
if(NOD > mass[i]) // Если предполгаемый НОД больше след. элемент массива,
{ NOD = mass[i]; } // тогда след.элемент - НОД.
}
if (!minus)
{
flag=1; // Флаг на true
while(flag==1) // Пока флаг = true делаем.
{
flag=0; // Флаг = false.
for(i=0; i<N; i++)
if(mass[i]%NOD!=0) // Если след. элемент массива делится на предпологаемый НОД без остатка,
{ flag=1; } // тогда ставим флаг на true.
NOD--; // Здесь уменьшаем значение НОД.
}
NOD++; // Здесь увеличиваем значение НОД.
printf("\n \n NOD = %d. \n", NOD);
}
else
{ printf("\n \n Oshibka! V massive nayden element <= 0."); // Вывести сообщение об ошибке.
}

Shmanich
Есть вариант проще:

int NOD_Function(int a, int b); // Объявляем функцию вычисления НОД.

int NOD_Function(int a, int b)
{ if (b==0) // Если второе число равно 0.
{return a; } // Вернуть значение первого.
else // Иначе
{ return NOD_Function(b, a%b); } // Вернуть значение функции НОД, используя рекурретность.
}




Думаю как применять эту функцию и как обойти случай, когда все элементы массива равны нулю - догадаетесь сами. smile.gif
Krjuger
Цитата
Думаю как применять эту функцию и как обойти случай, когда все элементы массива равны нулю - догадаетесь сами.

Ты в загадки с нами играешь что ли?Нам все равно и гадать нет нужны.
То что ты сделал не сработает на тесте а=10 б=0,оно выдаст 10.Так что думай дальше.
Shmanich
Цитата(Krjuger @ 1.06.2012 16:00) *

Ты в загадки с нами играешь что ли?Нам все равно и гадать нет нужны.

Может вам и форум этот не нужен? Зачем вы вообще здесь тусуетесь? Зачем он таким профи?

Цитата(Krjuger @ 1.06.2012 16:00) *

То что ты сделал не сработает на тесте а=10 б=0,оно выдаст 10.Так что думай дальше.


Вообще-то, согласно определению о НОД имеет место быть следующие равенства:
НОД(a, b) = НОД(b, a),
НОД(a, b) = НОД(-a, b)
НОД(a, 0) = |a|

Следовательно, НОД (10, 0) = |10| = 10. (0 делится на 10 и 10 делится на 10 без остатка).

Источник привести или сам найдешь? rolleyes.gif

Кстати, зная как таким образом вычислить НОД можно легко узнать наименьшее общее кратное wink.gif
Krjuger
Цитата
Может вам и форум этот не нужен? Зачем вы вообще здесь тусуетесь? Зачем он таким профи?

Если ты спрашиваеш,то спрашивай,а слова "догадайтесь сами" может произнести учитель ,давший своим студентам неполное решение. Увы,но вам пока что в роли учителя не выступать. И да вы не поняли,о чем я вам писал.Окей распишу поподробней.

// 1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <conio.h>
#include <stdlib.h>
#include <time.h>
const int N=5;

int NOD_Function(int a, int b); // Объявляем функцию вычисления НОД.


int NOD_Function(int a, int b)
{
if (b==0) // Если второе число равно 0.
{return a; } // Вернуть значение первого.
else // Иначе
{ return NOD_Function(b, a%b); } // Вернуть значение функции НОД, используя рекурретность.
}

int main()
{
int mass[N]={4, -4, 8, 16, 32}; // Объявляем массив.
int i, g, h, x, temp, NOD;
bool minus,flag;
NOD=mass[0];
/* srand(unsigned(time(NULL))); // Запуск генератора случайных чисел. */
printf("\n Massiv iz 5 elementov: \n");
for(i=0; i<N; i++)
{
/* mass[i]=rand()%10+1; */
printf("\n Mass[%d] = %d. ", i, mass[i]);
}

for(i=1; i<N; i++)
{
NOD=NOD_Function(NOD, mass[i]);
}
printf("\n \n NOD = %d. \n", NOD);
}


Я предположил,что вы использовали предыдущие наработки.Вот что получилось.

Кстати, на будущее, выкладываете полный код,потому что гадать, что у вас "скрывается за занавесом" никто не станет.
Как вам видно массив у нас 4, -4, 8, 16, 32 // Объявляем массив.
В ответе мы получаем число -4, что есть неверно.Надеюсь понятно почему??
Тоже самое мы получим при 4, 2, 8, -2, 32, в результате -2
Shmanich
Цитата(Krjuger @ 1.06.2012 17:21) *

Если ты спрашиваеш,то спрашивай,а слова "догадайтесь сами" может произнести учитель ,давший своим студентам неполное решение. Увы,но вам пока что в роли учителя не выступать. И да вы не поняли,о чем я вам писал.Окей распишу поподробней.


Так я спрашиваю! Но прежде чем получить внятный ответ получаю такие выпады, что моя задача банальна, что желающих помочь здесь нет и вообще я глухой!

Цитата(Krjuger @ 1.06.2012 17:21) *

Кстати, на будущее, выкладываете полный код,потому что гадать, что у вас "скрывается за занавесом" никто не станет.


Но вы же тут профи. Можете и сами догадаться куда какой фрагмент кода вставлять.

Кстати зачем вы в приведеном выше коде объявили "bool minus,flag" и "int g, h, x, temp", когда они нигде не испльзуются?

В данной программе как оказывается не задано рассматривать числа меньше 0, хотя по желаню можно и рассмотреть.
Krjuger
Цитата
Так я спрашиваю!

Может я не знаю русского языка,но "догадайтесь сами" это ниразу не вопрос.Либо это очередная попытка взять на слабо,либо это снизхождение,дескать, я кое-что сделал,а вы уж сами додумайте.
Цитата
Но вы же тут профи. Можете и сами догадаться куда какой фрагмент кода вставлять.

Слушайте,гадание на кофейной гуще это самое неблагодарное дело.
Например вы скидываете кусок программы и говорите, не работает.Ее дописывают до полноценной программы и она,о чудо, отрабатывает.Выясняется, что ошибка происходит у вас раньше,а другой человек написал все верно,или вы сделали какой нибудь хитрый финт ушами и все получается наоборот.
Цитата
Кстати зачем вы в приведеном выше коде объявили "bool minus,flag" и "int g, h, x, temp", когда они нигде не испльзуются?

Я просто скопировал из одного из предыдущих постов.
Цитата
В данной программе как оказывается не задано рассматривать числа меньше 0, хотя по желаню можно и рассмотреть.

Мне то откуда об этом знать.Вы задачу ставите.
Цитата
Но прежде чем получить внятный ответ получаю такие выпады, что моя задача банальна, что желающих помочь здесь нет и вообще я глухой!

Это не выпады,просто есть категория людей,которая приходит на форум и требует,чтобы им решили.Чаще всего таких людей просто игнорируют.
Как вы заметили,здесь форум и, как на большинстве форумов, помощ здесь абсолютно добровольная.
Вы попросили помощи,вам помогли,затем вы создали новую тему ,где "затем мне предложили другой вариант решения, который мне показался интереснее". По сути вы наплевали на труд того человека и теперь хотите,чтобы он помог вам исполнить вашу прихоть.Он вас вежливо послал искать при помощи дебага.Это одно из неотемлемых умений программиста.Вы же на это отреагировали "а слабо".Отсуда к вам и пошло такое отношение.
Вот если бы вы полазили с дебагом и сказали,у меня вот тут ошибка , не знаю как исправить, помогите,это одно. Вы же сказали,вот код, он не работает, давайте правьте,то есть сами ищите где ошибка,а это самое неблагодарное занятие.За подобное редко беруться.
За такое могут взяться,только если заинтересует сама задача,но извините, НОД замусолен уже до дыр, вот поэтому он и банален.
Про глухого вам никто не говорил,но вы как минимум несколько раз проигнорировали то,что я вам писал про ближайшее к среднему арифметическому.
Shmanich
Цитата(Krjuger @ 1.06.2012 18:31) *

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


1. Не прихоть, а просьба. 2. Труд уважаю, но если я для себя нашел вариант лучше это не значит, что я наплевал на труд собеседника. Просто в конкретно моем случае другое решение оказалось интереснее.

Цитата(Krjuger @ 1.06.2012 18:31) *


Вот если бы вы полазили с дебагом и сказали,у меня вот тут ошибка , не знаю как исправить, помогите,это одно.


А кто привел краткую функцию вычисление НОД в итоге? Пусть и только для положительных чисел? Кстати отсюда следует функция вычисления НОК:

int NOK_Function(int a, int b)
{
if (b==0) // Если последнее число равно 0,
{ printf ("\n \n Oshibka! V massive nayden 0"); // то вывести сообщение "Ошибка! В массиве найден 0".
return 0; } // Функция возврещает 0.
else
{ return a/NOD_Function(a, b)*b; } // Возвращаем значение а деленое на функцию НОД умноженное на b.
}



Цитата(Krjuger @ 1.06.2012 18:31) *

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


Если я еще не ответил по той теме это еще не значит, что я глух или проигноировал ваши рекомендации. Это значит, что решение данной задачи оставил на потом, либо она уже не актуальна.

И хватит уже офтипить!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.