Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

рекурсивная функция вычисления факториала

11K
19 апреля 2008 года
zuze
84 / / 07.03.2008
Вот код

Код:
unsigned short recfactorial(unsigned short num)
{
   unsigned short result;
   if (num == 1 || num == 0)
      result = 1;
   else
   {
      __asm
      {
           mov ax, num
           mov cx, recfactorial(num-1)
           mul cx
           jnc __local
           jmp __carry
           __local: mov result, ax
        }
   }
   return result;

    __carry: MessageBox(NULL, "Out of range1", NULL, NULL);
    return 0;  
}


Но я что-то не так сделал у меня компилятор ругается на строчку

 
Код:
mov cx, recfactorial(num-1)


Ошибка такая

E2188 Expression syntax

Подскажите пожалуйста, как сделать правильно.
3
19 апреля 2008 года
Green
4.8K / / 20.01.2000
Цитата: zuze

Подскажите пожалуйста, как сделать правильно.


Правильно - писать либо на С, либо на asm, а не путать эти языки.

Ты сам для себя можешь объяснить, что ты делаешь в строке
mov cx, recfactorial(num-1)

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

11K
19 апреля 2008 года
zuze
84 / / 07.03.2008
Попробовал так

Код:
unsigned short recfactorial(unsigned short num)
{
   unsigned short result;
   if (num == 1 || num == 0)
      result = 1;
   else
   {
      __asm
      {
           mov cx, [num]
           dec cx
           push cx
           call recfactorial
           mov cx, ax
           mov ax, [num]
           mul cx
           jnc __local
           jmp __carry
           __local: mov result, ax
        }
   }
   return result;
    __carry: MessageBox(NULL, "Out of range1", NULL, NULL);
    return 0;  
}


Но опять ошибки.

E2188 Expression syntax
E2329 Invalid combination of opcode and operands

Ругается на эту строчку

 
Код:
call recfactorial


Вчём же дело.
Помогите пожалуйста.
1.8K
19 апреля 2008 года
Evgeni
188 / / 14.06.2006
Советую предварительно закинуть в переменную int адресс твой процедуры, а потом уже эту переменную можно закинуть в стек и сделать ret(или jmp). Тут уж сам шамань
Ну это немного извращенно :))))))
11K
19 апреля 2008 года
zuze
84 / / 07.03.2008
Полный код, а то всё только функции.

factorial.h
Код:
#ifndef _FACTORIAL_H_
#define _FACTORIAL_H_

class Factorial
{
      public:
           Factorial();
           ~Factorial();
           unsigned short recfactorial(unsigned short num);
           unsigned short factorial(unsigned short num);
};
Factorial :: Factorial()
{
}
Factorial :: ~Factorial()
{
}
unsigned short Factorial :: recfactorial(unsigned short num)
{
   unsigned short result;
   if (num == 1 || num == 0)
      result = 1;
   else
   {
      result = recfactorial(num-1);
      __asm
      {
           mov cx, result
           mov ax, num
           mul cx
           jnc __local
           jmp __carry
           __local: mov result, ax
        }
   }
   return result;
    __carry: MessageBox(NULL, "Out of range1", NULL, NULL);
    return 0;  
}
unsigned short Factorial :: factorial(unsigned short num)
{
    unsigned short result = 1;
    for (unsigned short i = 2; i <= num; i++)
    {
        __asm
        {
             mov ax, result
             mov cx, i
             mul cx
             jnc __local
             jmp __carry
             __local: mov result, ax
        }
    }
    return result;
    __carry: MessageBox(NULL, "Out of range2", NULL, NULL);
    return 0;
}
#endif


Основной файл (Unit1.cpp)
Код:
//------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "factorial.h"
//------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
unsigned short numfactorial;
Factorial Factorial1;
//------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    numfactorial = StrToInt(Edit1->Text);
    Edit2->Text =  IntToStr(Factorial1.recfactorial(numfactorial));
}
//------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    numfactorial = StrToInt(Edit1->Text);
    Edit3->Text = IntToStr(Factorial1.factorial(numfactorial));
}
//------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
    if (!Edit1->Text.IsEmpty())
       Edit1->Clear();
    if (!Edit2->Text.IsEmpty())
       Edit2->Clear();
    if (!Edit3->Text.IsEmpty())
       Edit3->Clear();
    Edit1->ReadOnly = false;
}
//------------------------------------------------------------------------
void __fastcall TForm1::Edit1Change(TObject *Sender)
{
  if (Edit1->Text.IsEmpty())
     return;
  int i;
  if (TryStrToInt(Edit1->Text, i))
  {
     if (i > -1)
     {
        if (i > 65535)
        {
           MessageBox(0, "Вы ввели значение больше чем 65535!","Сообщение", MB_OK);
           Edit1->Clear();
        }
        AnsiString mynull = Edit1->Text;
        if (mynull[1] == '0')
           Edit1->ReadOnly = true;
     }
     else
     {
         MessageBox(0, "Вы ввели отрицательное число!","Сообщение", MB_OK);
         Edit1->Clear();
     }
  }
  else
  {
      MessageBox(0, "Введенный текст не является числом!","Сообщение", MB_OK);
      Edit1->Clear();
  }
}
//------------------------------------------------------------------------


Исправил с 9 всё работает, а вот если ввести 65535 не работает, только не рекурсивная функция работает правельно, почему и как поправить рекурсивную функцию?

Cообщение "Out of range1" должно выводится не только при вводе 9, а 9 и больше?. В моей программе ограничение стоит на ввод не больше 65535.
Я ввожу 65535 и хочу вычислить факториал с помощью рекурсивной функции и возникает ошибка.

Ошибка такая.
Выскакивает окно Debugger Exception Notification в этом окне написано
Project factorial.exe raised exception EStackOverflow with message 'Stack overflow'. Process stopped. Use step or Run continue.

Как поправить рекурсивную функцию, помогите пожалуйста.
3
19 апреля 2008 года
Green
4.8K / / 20.01.2000
Объясни, зачем этот монстроидальный код?
Ты принимаешь участие в конкурсе на самый бессмысленный код?
Ведь задача решается в три строчки, без классов, без ассемблера и даже без рекурсии. Они здесь совершенно не нужны.
33K
20 апреля 2008 года
ACW-Coder
17 / / 02.01.2008
Код:
void main()
{
    unsigned long ddNumber = 5, // for example
                   ddResult;

    __asm
    {
        mov ecx, ddNumber

        mov eax, 1
LP:     mul ecx
        loop    LP

        mov ddResult, eax
    }
}


А ведь действительно, всего 3 строчки кода, а факториал-то тоже умеют считать! Чудеса какие-то... :eek:
1.8K
20 апреля 2008 года
igor_nf
256 / / 13.12.2006
Кто нибудь может объяснить, зачем здесь асм? Если уж пишете на Си, то на Си и пишите. Или тогда на чистом асме. Сама задача вычисления факториала на Си решается элементарно:

 
Код:
unsigned long long fac(int val) {

   unsigned long long fact;
   int i;

   for(i = 1,fact = 1; i <= val && (fact *= i); ++i);

return fact;
}
3
20 апреля 2008 года
Green
4.8K / / 20.01.2000
Цитата: igor_nf
Кто нибудь может объяснить, зачем здесь асм? Если уж пишете на Си, то на Си и пишите. Или тогда на чистом асме. Сама задача вычисления факториала на Си решается элементарно:

 
Код:
unsigned long long fac(int val) {

   unsigned long long fact;
   int i;

   for(i = 1,fact = 1; i <= val && (fact *= i); ++i);

return fact;
}


Ну если убрать ошибки из этого кода, то это будет то, что нужно автору.

1.8K
20 апреля 2008 года
igor_nf
256 / / 13.12.2006
Код:
#include <stdio.h>

unsigned long long fac(int val) {

   unsigned      long long fact;
   int i;

   for(i = 1,fact = 1; i <= val && (fact *= i); ++i);

return fact;
}

int main(int ac, char **av) {

   int i;

   for(i = 0; i < 10; ++i)
      printf("Fac of %d is %lld\n", i, fac(i));

return 0;
}


Результат:
 
Код:
Fac of 0 is 1
Fac of 1 is 1
Fac of 2 is 2
Fac of 3 is 6
Fac of 4 is 24
Fac of 5 is 120
Fac of 6 is 720
Fac of 7 is 5040
Fac of 8 is 40320
Fac of 9 is 362880


Неосилил. Green, где ошибка-то?
3
20 апреля 2008 года
Green
4.8K / / 20.01.2000
Цитата: igor_nf

Результат:
 
Код:
Fac of 0 is 1
Fac of 1 is 1
Fac of 2 is 2
Fac of 3 is 6
Fac of 4 is 24
Fac of 5 is 120
Fac of 6 is 720
Fac of 7 is 5040
Fac of 8 is 40320
Fac of 9 is 362880


Неосилил. Green, где ошибка-то?


Это не является удовлетворительным набором тестов, т.к. не учитываются граничные значения.
Смотрим:

 
Код:
Fac of -1 is 1
Fac of 66 is 0

кроме того у автора топика функция имеет сигнатуру:
unsigned short recfactorial(unsigned short num)
а не
unsigned long long fac(int val)
1.8K
20 апреля 2008 года
igor_nf
256 / / 13.12.2006
Цитата:

Это не является удовлетворительным набором тестов, т.к. не учитываются граничные значения.



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

 
Код:
unsigned short recfactorial(unsigned short num)


Я не понимаю, почему short - автору что, памяти так жалко?
29K
21 апреля 2008 года
Zloi_lamer
9 / / 23.01.2008
ну что вы прицепились, может человеку надо написать программу на Си со вставкой кода из Ассемблера. Аsm легко связать с языками более высокого уровня. Главное учитывать несколько правил, и всё ок ;)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог