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


Автор: FraiDex 16.12.2009, 23:49
user posted image

Автор: mr.Anderson 17.12.2009, 00:32
Понадобится использовать длинную арифметику, ни в один стандартный тип число такого размера не укладывается. Почитай про длинную арифметику. Если вкратце, это механика хранения числа как совокупности его цифр, записанных в массив с правого края.

Автор: FraiDex 17.12.2009, 01:50
Спасибо буду разбираться. Ещё вопрос, как предварительно узнать число элементов в массиве? Оно ведь изначально неизвестно.

Автор: t_gran 17.12.2009, 10:03
Цитата

Оно ведь изначально неизвестно

А вы ограничьте тип, ведь стандартные типы данных тоже свои лимит имеют. В общем предлагаю свой код, правда написан с колена т.к. времени достаточно не было. В результате проверку на лимит расчёта не делал, но под ваши требования она в принципе подходит (я имею в виду расчёт факториала).
Код

const
   CLength= 256;
type
   TDigit= array [0..CLength] of word; // В '0'-ом указывается фактическая длина числа
{-----------------------------------------------}
// Конвертируем longint в TDigit
procedure PushDigit (var theDig: TDigit; theOrigDig: longint);
var
   i: word;
begin
   i:= 0;
   while (theOrigDig <> 0) do
   begin
      inc(i);
      theDig[i]:= theOrigDig mod 10;
      theOrigDig:= theOrigDig div 10;
   end;
   theDig[0]:= i;
end;
{-----------------------------------------------}
// Выполняем смещение влево на заданное количесво позиций
function DisplaceLeft (theDig: TDigit; theStep: word): TDigit;
var
   i: word;
   result: TDigit;
begin
   for i:= 1 to theStep do
      result[i]:= 0;
   for i:= 1 to theDig[0] do
      result[i+theStep]:= theDig[i];
   result[0]:= theDig[0] + theStep;
   DisplaceLeft:= result;
end;
{-----------------------------------------------}
function SummDigit (theOneDig, theTwoDig: TDigit): TDigit;
var
   i, buff: word;
   result: TDigit;
   pOneDig, pTwoDig: ^TDigit; // Первый - меньшее число, второй - большее
begin
   if (theOneDig[0] < theTwoDig[0]) then
   begin
      pOneDig:= @theOneDig;
      pTwoDig:= @theTwoDig;
   end
   else
   begin
      pOneDig:= @theTwoDig;
      pTwoDig:= @theOneDig;
   end;
   buff:= 0;
   for i:= 1 to pTwoDig^[0] do
   begin
      if (pOneDig^[0] < i) then
         pOneDig^[i]:= 0;
      result[i]:= pOneDig^[i] + pTwoDig^[i] + buff;
      if (result[i] < 10) then
         buff:= 0
      else
      begin
         buff:= 1;
         result[i]:= result[i] mod 10;
      end;
   end;
   if (buff <> 0) then
   begin
      inc(i);
      result[i]:= buff;
   end;
   result[0]:= i;
   SummDigit:= result;
end;
{-----------------------------------------------}
// Умножаем второе число на первое
function MultipliDigit (theOneDig, theTwoDig: TDigit): TDigit;
var
   i, j, buff: word;
   result, temp: TDigit;
begin
   PushDigit(result, 0);
   for j:= 1 to theTwoDig[0] do
   begin
      buff:= 0;
      for i:= 1 to theOneDig[0] do
      begin
         temp[i]:= theOneDig[i] * theTwoDig[j] + buff;
         if (temp[i] < 10) then
            buff:= 0
         else
         begin
            buff:= temp[i] div 10;
            temp[i]:= temp[i] mod 10;
         end;
      end;
      if (buff <> 0) then
      begin
         inc(i);
         temp[i]:= buff;
      end;
      temp[0]:= i;
      result:= SummDigit(result, DisplaceLeft(temp, j-1));
   end;
   MultipliDigit:= result;
end;
{-----------------------------------------------}
procedure PrintDigit (theDig: TDigit);
var
   i: word;
begin
   for i:= theDig[0] downto 1 do
      write(theDig[i]);
end;
{-----------------------------------------------}
function Factorial (theNumber: longint): TDigit;
var
   i: longint;
   result, temp: TDigit;
begin
   PushDigit(result, 1);
   for i:= 1 to theNumber do
   begin
      PushDigit(temp, i);
      result:= MultipliDigit(result, temp);
   end;
   Factorial:= result;
end;
{-----------------------------------------------}

var
   i: longint;
begin
   write('Число для вычисления факториала: ');
   readln(i);
   write('Результат: ');
   PrintDigit(Factorial(i));
end.


Если нужен более высокий порядок, то поменяйте значение константы CLength на необходимое. Только учитывайте, что размерность ограничена типом WORD. Если нужно ещё больше, то укажите другой тип. Понимаю, что такой подход ресурсо-неэкономичный, но я уже писал, что писалось всё с колена. ООП бы сюда прикрутить, было бы удобнее. smile

Автор: FraiDex 10.1.2010, 00:07
а может есть у кого решение самой задачи?

Автор: mr.Anderson 10.1.2010, 04:35
Цитата
Спасибо буду разбираться

Цитата
а может есть у кого решение самой задачи?

Неужели надоело разбираться? smile 

Автор: hkdkest 10.1.2010, 18:48
есть на дельфи исходник http://codingrus.ru/infusions/pro_download_panel/download.php?did=392 можно переделать

http://codingrus.ru/infusions/pro_download_panel/download.php?did=392

Автор: FraiDex 15.1.2010, 18:15
Всем спасибо!!! Слава богу разобрался...

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