Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C++] Описание функции


Автор: Tsunameh 9.5.2007, 12:06
Доброго времени суток ! 
Возникла вот такая задачка ; просьба написать код таким образом , чтобы можно было разобраться самостоятельно с книжкой ) тоесть наиболее простая запись , просто чтобы работало )

Итак:

Описать функцию 

F(n,m) = (n!*m!)/(n*m)!  ,  n,m >=0. 

При этом необходимо определить функцию , вычисляющую факториал. 




Заранее спасибо )

Автор: zkv 9.5.2007, 12:27
Код

unsigned long  Fuct( unsigned long  n )
{
    if( n < 0 )
        ;//ошибка в данных надо как то предупредить и что то сделать
    unsigned long ulRet = 1;//0! == 1 по определению
    for( int i = 2; i <= n; ++i )
        ulRet *= i;
    return ulRet;
}

unsigned long  F( unsigned long  n, unsigned long  m )
{
    if( n < 0 || m < 0 )
        ;//ошибка в данных надо как то предупредить и что то сделать
    
    return (Fuct( n ) * Fuct( m )) / Fuct(m*n);//Внимание! Деление целочисленное!
}

Автор: GIK 9.5.2007, 12:32
Цитата

При этом необходимо определить функцию , вычисляющую факториал. 

В смысе она отдельна должна быть? Ну короче вот пока, если надо переделаю smile
Код

#include<conio.h>
#include<iostream.h>
#include<stdlib.h>
#include<cstdlib.h>
#include<stdio.h>
#include<cstdio.h>

int F(const int n, const int m){
  int i, ran=1, ran2=1, ran3=1;
  //Âû÷èñëÿåì ôàêòîðèàë n
  for(i=2; i<=n; i++)
   ran*=i;
  for(i=2; i<=m; i++)
   ran2*=i;
  //Âû÷èñëÿåì ôàêòîðèàë n*m
  for(i=2; i<=(n*m); i++)
   ran3*=i;

  i=(ran*ran2)/ran3;
  return i;
}
int main(int argc, char* argv[])
{
 int n=1, m=2;
 printf("%d", F(n,m));

  //F(n,m) = (n!*m!)/(n*m)!  ,  n,m >=0.

    getch();
        return 0;
}


Добавлено через 1 минуту и 22 секунды
Упс, опоздал, решение уже есть smile

Автор: keenara 9.5.2007, 12:48
Позволю себе несколько замечаний (zkv заранее сорри).
1)Не вижу никакого смысла в двойной проверке корректности: если что-то не так, то внутренняя функция Fuct все равно скажет об ошибке и еще и передаст наружу сигнал сбоя.
2)unsigned и т.п. могут показаться сложными, а автор просил
Цитата
написать код таким образом , чтобы можно было разобраться самостоятельно с книжкой

3)Факториал - по опредлению рекурсивная процедура, поэтому вычислять ее при помощи рекурсии сам Джа велел.

Поэтому предлагаю свой, более простой вариант.
Код

#include <iostream.h>
long Fuct(int n);
long F(int n, int m);
int main(){
int i;
cout<<"Введите число"; cin>>i;
cout<<F(i)<<endl;
return 0;
}

long Fuct(int n)
{
    if( n < 0 ){cout<<"Некорректное значение аргумента"<<endl; return 0;}
    if(n==0) return 1;
    else return n * Fuct(n-1);
}

long  F(int n, int m)
{
        return (Fuct( n ) * Fuct( m )) / Fuct(m*n);
}

Автор: GIK 9.5.2007, 13:02
Цитата

поэтому вычислять ее при помощи рекурсии сам Джа велел.

Согласен с Вами, а кто такой Джа, простите?  smile 

Автор: Tsunameh 9.5.2007, 13:19
Спасибо огромное и бальшущий вам риспект ) приду еще ))

Автор: keenara 9.5.2007, 13:30
Захады дарагой! мы тут как раз на ваших задачках прокачиваемся  smile 

Автор: zkv 9.5.2007, 14:06
Цитата(keenara @  9.5.2007,  12:48 Найти цитируемый пост)
1)Не вижу никакого смысла в двойной проверке корректности: если что-то не так, то внутренняя функция Fuct все равно скажет об ошибке и еще и передаст наружу сигнал сбоя.

Уважаемый(ая) keenara, не стояло задачи написать программу, была задача написать отдельные функции, вы уверены, что она нигде больше не будет вызываться? 
Даже если не будет, лишняя проверка никогда еще никому не помешала smile
Цитата(keenara @  9.5.2007,  12:48 Найти цитируемый пост)
2)unsigned и т.п. могут показаться сложными, а автор просил

не буду спорить, сужу по себе, я бы не испугался smile
Цитата(keenara @  9.5.2007,  12:48 Найти цитируемый пост)
3)Факториал - по опредлению рекурсивная процедура, поэтому вычислять ее при помощи рекурсии сам Джа велел.

не спорю, рекурсия хорошо смотрится, да и повозиться с ней иногда интересно из спортивного интереса, но по возможности следует ее избегать (стек не резиновый smile )

Автор: keenara 9.5.2007, 14:14
Цитата
не стояло задачи написать программу, была задача написать отдельные функции

Некоторые особо одаренные товарищи из числа авторов тем в этом разделе не в состоянии собрать прогу из готовых функций smile . Я конечно понимаю что с методологической точки зрения вредно думать за них, но помочь тоже хочецца
Цитата
вы уверены, что она нигде больше не будет вызываться?

В любом случае если косячок с  аргументом будет то функция самого факториала нас все равно носом в это дело тыкнет
Цитата
лишняя проверка никогда еще никому не помешала smile

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

я тоже, но многие писаются при виде этих "страшных" слов  smile 
Цитата
но по возможности следует ее избегать (стек не резиновый smile )

Это что же такое туда надо засунуть чтобы стек переполнить?  smile 

Автор: zkv 9.5.2007, 14:24
keenara, есть некоторые принципы, которых я придерживаюсь (по возможности не применять рекурсию, проверять ошибки где только можно - производительность перетопчется, особенно в таком контексте smile ), никому навязывать их я не собираюсь. Я сказал свое слово. smile

Автор: keenara 9.5.2007, 14:31
Цитата
есть некоторые принципы, которых я придерживаюсь

Очень правильные принципы на самом деле, я тоже в СЕРЬЕЗНЫХ задачах их придерживаюсь, но в данном контексте... 
Ты пойми, я ж не из принципа все это говорю, а из сочуствия к кренделям которым все это дело придется защищать злобным преподам  smile 
Цитата
проверять ошибки где только можно

Гы, тогда по логике нужно еще и добавить проверку корректности ввода в том плане чтобы туда буквы не вводили smile . А что, шутки шутками, а наш препод при тестировании наших "шедевров" типа этого обожал вводить куда ни попадя фразу "11 попка дурак", после чего прогу отправляли на доработку, потому что она в лучшем случае выдавала лажу а в худшем - вешала всю среду разработки  smile 

Автор: Rockie 9.5.2007, 18:36
Цитата(keenara @  9.5.2007,  12:48 Найти цитируемый пост)
Поэтому предлагаю свой, более простой вариант.

smile
Код

#include <iostream>    

int fact(int n)
{
    if(n==0) return 1;
    else return n*fact(n-1);
}

int main()    
{
    std::cout<<fact(5);

    return 0;    
}


Добавлено через 3 минуты и 58 секунд
еще на http://ru.wikipedia.org/wiki/Факториал:
Код
       int factorial(int x) {
         return (x == 0)?(1):(x * factorial(x - 1));
       }



Автор: keenara 9.5.2007, 18:45
Хе, я тоже тернарный оператор люблю, он красивый и почему-то в основном программерами незаслуженно забыт  smile 

Автор: GIK 10.5.2007, 13:01
Если уж говорить о загружанности компа, и о прочих подобных вещах, то ему  можно немого помочь:
Код

int factorial(int x) {
         return (x == 1)?(3):(x * factorial(x - 1));
     }

Автор: zkv 10.5.2007, 13:13
Цитата(GIK @  10.5.2007,  13:01 Найти цитируемый пост)
int factorial(int x) {
         return (x == 1)?(3):(x * factorial(x - 1));
     }

не перемудрил? smile что делает эта функция?

Автор: Rockie 10.5.2007, 13:21
keenara

Цитата(keenara @  10.5.2007,  08:37 Найти цитируемый пост)
Я например люблю нестандартные приемы

1) Тернарный оператор это стандартный прием. Другое дело что к примеру мне он не нравится по причине нечитабельности. Равно как мне не нравится switch, мне понятнее if-else, if-else.. Впрочем это субъектив.
2) Если писать что-то для себя, то хоть 
Код

define ++ --

Но если ваш код смотрит кто-то другой, "нестандартные приемы" неуместны.

GIK, не знал, что факториал единицы равен трем. 


Автор: dizzy1984 10.5.2007, 13:29
наВернА гИк ХаТел эТА?
Код

int f(int x)
{
    return x == 1 ?  1 : ( x == 2 ? 2 : (x * f(x - 1)) );
}


но пАможит илИ наврИдИт - сПорныЙ вАпрос

Автор: keenara 10.5.2007, 13:56
Цитата
Тернарный оператор это стандартный прием.

Стандартный - понятие относительное. Именно этот прием очень многие не используют
Цитата
Но если ваш код смотрит кто-то другой, "нестандартные приемы" неуместны.

С этим поспорю. Когда я пишу программы для всяких "Центров помощи", то естественно стараюсь сделать программу как можно проще и нагляднее, пусть даже в ущерб качеству. Но когда я пишу более серьезные вещи, СМОТРЕТЬ код (а не просто юзать) будут достаточно опытные кодеры, которые все эти нестандартные приемы выучили когда я еще погремушки в детсаду дебаггила  smile 
А на всякий случай все равно все непонятные места документирую. Пара комментов и все станет ясно.

Автор: Rockie 10.5.2007, 14:04
Цитата(dizzy1984 @  10.5.2007,  13:29 Найти цитируемый пост)
но пАможит илИ наврИдИт - сПорныЙ вАпрос

dizzy1984, навредит, так как этот вариант не подсчитает 0!
Цитата(keenara @  10.5.2007,  13:56 Найти цитируемый пост)
 Но когда я пишу более серьезные вещи, СМОТРЕТЬ код (а не просто юзать) будут достаточно опытные кодеры, которые все эти нестандартные приемы выучили когда я еще погремушки в детсаду дебаггила smile  

Откуда они знают эти приемы, если они нестандартные? Мы кажется про-разному понимаем это слово  smile 


Автор: GIK 10.5.2007, 14:06
Точно, перемудрил  smile , вот что хотел:
Код

int factorial(int x) {
     if(x>1)
         return (x == 2) ? (2):(x * factorial(x - 1));
     else if(x>0) return 1;      
}


Добавлено через 1 минуту
Вроде больше некуда урезать smile 

Автор: zkv 10.5.2007, 14:15
Цитата(keenara @  10.5.2007,  13:56 Найти цитируемый пост)
Но когда я пишу более серьезные вещи, СМОТРЕТЬ код (а не просто юзать) будут достаточно опытные кодеры, которые все эти нестандартные приемы выучили когда я еще погремушки в детсаду дебаггила  smile 
А на всякий случай все равно все непонятные места документирую. Пара комментов и все станет ясно.

по вашему получается, что профессионалы пишут код так, что потом  его никто без поллитры не разберет? smile 

GIK, (ехидно улыбаясь smile ), а если х == 0 придет (для которого факториал == 1)? А если отрицательное число?

Автор: GIK 10.5.2007, 14:22
Код

int factorial(int x) {
     if(x>1)
         return (x == 2) ? (2):(x * factorial(x - 1));
     else if(x>0) return 1;   
     else return 0; //"матерное слово"


Автор: keenara 10.5.2007, 15:13
Это мы спьяну пишем не думая, а потом слова назад по-быстрому берём. Эсперанто прикопался к одной из прог (типа ошибку) заметил, но понял что не прав и заменил пост на 44
Я по ошибке прогу не в тот топик запостила и заменила на 11.

Это все из-за того что невозможно полностью удалить пост. Вот и приходится его заменять откровенным флудом чтобы его кильнули

Автор: Anikmar 10.5.2007, 15:34
Цитата(keenara @  10.5.2007,  15:13 Найти цитируемый пост)
Это мы спьяну пишем не думая, а потом слова назад по-быстрому берём. Эсперанто прикопался к одной из прог (типа ошибку) заметил, но понял что не прав и заменил пост на 44
Я по ошибке прогу не в тот топик запостила и заменила на 11.

Это все из-за того что невозможно полностью удалить пост. Вот и приходится его заменять откровенным флудом чтобы его кильнули 
 smile 
Ну только у компьютерщиков существует такой сленг. Ни в одной специальности я больше такого не видел.  smile 

Одна фраза "кильнуть пост". Всем понятно, но ведь это термин водный. Как можно перевернуть пост вверх ногами?!

Это я так, прикалываюсь.  smile 

Автор: Tsunameh 13.5.2007, 14:16
Возникла проблема .. ни один из вышеперечисленных кодов не хочет правильно работать на билдере. Если можно , напишите код так , чтобы работал на билдере , тк мы в этой среде работаем ... *(

Автор: zkv 13.5.2007, 14:22
Tsunameh, я плохо знаком с билдером, но во-первых, приложение должно быть консольным, во-вторых, показывайте что именно пишите, и что не получается (вместе с кодом ошибки, и номером строки в коде).

Автор: Tsunameh 13.5.2007, 14:37
Код

#include<conio.h>
#include<iostream.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>

void main();
int F(int n, int m)

{
 clrscr();
  int i, ran1=1, ran2=1, ran3=1;

{
cout<<"Vvedite chisla n i m : ";
cin>>n;
cout<<" ";
cin>>m;
  for(i=2; i<=n; i++)
   ran1*=i;
  for(i=2; i<=m; i++)
   ran2*=i;

  for(i=2; i<=(n*m); i++)
   ran3*=i;

  i=(ran1*ran2)/ran3;
  cout<<"Znachenie = ";
  cout<<i;
  getch();
}
return(i);
}


компилятор не нашел ошибки , но при запуске программы пишет Undefined symbol _main in module c0.ASM в окне компилятора.


M
Guedda
Не забываем пользоваться кнопкой "Код"

Автор: zkv 13.5.2007, 14:52
и кто такой код вам приводил? smile
Вот, вероятно, то, что вы хотели изобразить:
Код

#include<conio.h>
#include<iostream.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>

//int F(int n, int m); - это что?

int main()
{
 clrscr();
  int i, ran1=1, ran2=1, ran3=1;


cout<<"Vvedite chisla n i m : ";
cin>>n;
cout<<" ";
cin>>m;
  for(i=2; i<=n; i++)
   ran1*=i;
  for(i=2; i<=m; i++)
   ran2*=i;

  for(i=2; i<=(n*m); i++)
   ran3*=i;

  i=(ran1*ran2)/ran3;
  cout<<"Znachenie = ";
  cout<<i;
  getch();

return i;
}

Автор: Tsunameh 13.5.2007, 14:54
Я сам себе его наприводил следуя указаниям выше )) видимо неудачно, буду проверять вашу версию.

Добавлено через 5 минут и 35 секунд
Вопрос : что означает ran1*=i; ? Конкретнее "*=" непонятно )

Автор: zkv 13.5.2007, 15:07
Код

ran1*=i;
все равно что:
Код

ran1 = ran1 * i;

Автор: Tsunameh 13.5.2007, 15:33
Вот бы вроде тот код который мне нужен:

Код

#include<conio.h>
#include<iostream.h>
#include<stdlib.h>
#include<math.h>
#include<stdio.h>

int F(const int n, const int m)


{  int i, ran=1, ran2=1, ran3=1;
   double j;
 { for(i=2; i<=n; i++)
   ran*=i;
  for(i=2; i<=m; i++)
   ran2*=i;
  for(i=2; i<=(n*m); i++)
   ran3*=i;

  j=(ran*ran2)/ran3;
  cout<<"Znachenie faktoriala = "<<j;
 }
{
 int n=3, m=4;
 printf("%d", F(n,m));

  //F(n,m) = (n!*m!)/(n*m)!  ,  n,m >=0.

    getch();
    return 0;
}
}


Но опять же пишет Undefined symbol _main in module c0.ASM  ... (((


 ! 
Guedda
Пользуйтесь кнопкой "Код"!О том, как это делать, прочитайте здесь!

Автор: zkv 13.5.2007, 16:11
Tsunameh, грубо говоря, в программе обязательно должна быть функция 
int main", она является точкой входа в приложение, те с нее начинается выполнение.

Автор: Tsunameh 13.5.2007, 16:14
Все , саму суть программы описал , теперь нужно понять как вызывать выполнение программы с помощью функции.. )

Автор: dizzy1984 14.5.2007, 05:30
Вам много раз об этом сказали, но вы, почему-то, оказались глухи к гласу разума.
Любая программа на c/с++ обязана начинаться только с функции main.
Вот пример
Код

int main()
{
    return 0;
}

простейшей программы

Автор: zkv 14.5.2007, 08:15
Цитата(dizzy1984 @  14.5.2007,  05:30 Найти цитируемый пост)
Любая программа на c/с++ обязана начинаться только с функции main.

это приближенно, точку входа даже задавать можно (Linker->Entry point), но я еще ни разу не пользовался. smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)