Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.03.2012, 23:06   #1
noskovgleb
 
Регистрация: 22.10.2009
Сообщений: 8
По умолчанию 100! Одним числом

Есть такой код, который вычисляет факториал 100, очень хотелось бы разобраться как он работает, вот собственно сам код:
Код:
#include<iostream.h>
#include<conio.h>
void main()
{  int i,k,n=200,A[200];
   clrscr();
   for(i=0; i<n; i++)
      A[i]=0;
   A[0]=1;
   for(k=0; k<100; k++)
   {  for(i=0; i<n; i++)
         A[i]*=(k+1);
      for(i=0; i<n; i++)
      {  A[i+2]+=(A[i]/100);
         A[i+1]+=(A[i]%100/10);
         A[i]%=10;
      }
   }
   for(i=0; i<n; i++)
      cout<<A[n-i-1];
   cout<<endl;
   getch();
}
noskovgleb вне форума Ответить с цитированием
Старый 18.03.2012, 01:19   #2
Granus
С++
Форумчанин
 
Аватар для Granus
 
Регистрация: 22.09.2008
Сообщений: 791
По умолчанию

Делается обычная длинная арифметика. A - массив десятичных чисел числа.
Число = A[0] + 10 * A[1] + 100 * A[2] + ...
Изначально число в A - 1. Потом оно последовательно умножается на все числа до 100. Для этого мы сначала каждый элемент массива умножаем на k, после чего обрабатываем переполнение (случаи, когда A[i] >= 10, мы все-таки цифры в них храним). Собственно, вот этот код
Код:
for(i=0; i<n; i++)
      {  A[i+2]+=(A[i]/100);
         A[i+1]+=(A[i]%100/10);
         A[i]%=10;
      }
и избавляет от переполнения.
Форматируйте код, будьте людьми.
Granus вне форума Ответить с цитированием
Старый 18.03.2012, 17:41   #3
noskovgleb
 
Регистрация: 22.10.2009
Сообщений: 8
По умолчанию

а можно по подробнее, как будто если бы вы чайнику объясняли?
как работает особенно эта конструкция:

Код:
for(i=0; i<n; i++)
         A[i]*=(k+1);
      for(i=0; i<n; i++)
      {  A[i+2]+=(A[i]/100);
         A[i+1]+=(A[i]%100/10);
         A[i]%=10;
      }
noskovgleb вне форума Ответить с цитированием
Старый 19.03.2012, 10:41   #4
Granus
С++
Форумчанин
 
Аватар для Granus
 
Регистрация: 22.09.2008
Сообщений: 791
По умолчанию

Для начала, чуть-чуть подправлю, чтобы было понятнее

Код:
for(k=1; k<=100; k++)
   {  for(i=0; i<n; i++)
         A[i]*=k;
      for(i=0; i<n; i++)
      {  A[i+2]+=(A[i]/100);
         A[i+1]+=(A[i]%100/10);
         A[i]%=10;
      }
   }
Этот кусок кода - умножение длинного числа на k (хотя, думаю, Вы догадались).
Напомню, в массиве A мы храним десятичные цифры нашего числа. X = A[0] + 10 * A[1] + 100 * A[2] + ... + 10^199 * A[199];
Из этого представления видно, что чтобы умножить число на k (где k - "короткое" число, помещающееся в базовые типы данных), мы можем каждую цифру умножить на k:
Код:
for(i=0; i<n; i++)
         A[i]*=k;
Но здесь возникает проблема: в массиве будут уже не цифры, а числа (причем числа <= 900: изначально там цифры <= 9, k <= 100 значит результат умножения <= 900).
Приведенное выше разложение все еще будет работать, но вот нам дальше работать с этим числом трудновато (все операции считают, что в массиве только цифры). Поэтому мы боремся с переполнением:
Код:
for(i=0; i<n; i++)
      {  A[i+2]+=(A[i]/100);
         A[i+1]+=(A[i]%100/10);
         A[i]%=10;
      }
Как мы с ним боремся? Мы знаем, что получившиеся в массиве числа у нас <= 900, то есть лишних цифр в нем не более двух (сотни A[i]/100 и десятки A[i]%100/10). Поэтому в следующую ячейку мы прибавляем число десятков, через одну - число сотен, после чего в данной ячейке оставляем только одну цифру - число единиц. От этого могли еще увеличиться значения дальше, но их переполнение цикл обработает позже, поэтому все сработает.
Форматируйте код, будьте людьми.
Granus вне форума Ответить с цитированием
Старый 21.03.2012, 02:36   #5
noskovgleb
 
Регистрация: 22.10.2009
Сообщений: 8
По умолчанию

вроде бы все понятно. Гранусу большое спасибо за ответ.
Очень помог.
noskovgleb вне форума Ответить с цитированием
Старый 21.03.2012, 06:44   #6
Karmadon
Пользователь
 
Аватар для Karmadon
 
Регистрация: 28.02.2012
Сообщений: 46
По умолчанию

У меня подобный пример но переписан под вектор
Но работает только на коротких числах (до 26!)
а потом только конец цифры
Код:
#include<iostream.h>
#include <vector.h>

int main()
{   
    int factor(5);
    int i(0);
    int k(0);
    vector<int> A(0);
    
    A.push_back(1);
    A[0]=1;
    
    for(k=0; k<factor; k++)
        {
            A.push_back(0);
        
        for(i=0; i<A.capacity(); i++)
            {
                A[i]*=(k+1);
            }
        
            for(i=0; i<A.capacity(); i++)
                {  
                    A[i+2]+=(A[i]/100);
                    A[i+1]+=(A[i]%100/10);
                    A[i]%=10;
                }
        }
    for(i=0; i<A.size(); i++)
        {
            cout<<A[A.size()-i-1];
        }
    
   cout<<endl;
    return 1;
}
Что не так?
"THE ONLY WAY TO GET SMARTER IS BY PLAYING A SMARTER OPPONENT." -- Fundamentals of Chess 1883

Последний раз редактировалось Karmadon; 21.03.2012 в 11:19.
Karmadon вне форума Ответить с цитированием
Старый 21.03.2012, 12:02   #7
Karmadon
Пользователь
 
Аватар для Karmadon
 
Регистрация: 28.02.2012
Сообщений: 46
Лампочка работающий вариант

Вот работающий варинат (может пригодится)

Код:
#include    <iostream.h>
#include    <vector.h>

int main()
{   
    bool nulic(true);
    int factor(1000);
    int i(0);
    int k(0);
    vector<int> A(0);
    
    A.push_back(1);
    A[0]=1;
    
    
    for(k=0; k<factor; k++)
        {
        A.push_back(0);
        
        for(i=0; i<A.size(); i++)
            {
            A[i]*=(k+1);
            }
        A.push_back(0);
        A.push_back(0);
        for(i=0; i<A.size(); i++)
            {  
                A[i+2]+=(A[i]/100);
                A[i+1]+=(A[i]%100/10);
                A[i]%=10;
            }
        }
    
    
    for (i=A.size(); i>=0; i--) 
        {
        
        if (A[i]==0) 
            {
            if (!nulic) 
                { 
                    cout<<A[i];
                }
            }
        else
            {
                cout<<A[i];
                nulic=false;
            }

        }
   
    cout<<endl;

    return 1;
}
"THE ONLY WAY TO GET SMARTER IS BY PLAYING A SMARTER OPPONENT." -- Fundamentals of Chess 1883
Karmadon вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Воплотить идею: for i:=0 to 100 Edit[i].text:=random(100) tigr1991 Общие вопросы Delphi 6 29.09.2010 18:53
Найти произведение всех чётных чисел от -100 до 100. Makcumqa Помощь студентам 8 18.03.2010 22:31
заполнить файл целыми числами из отрезка [—100; 100] с помощью датчика случайных чисел. ALEX-7-7-7 Паскаль, Turbo Pascal, PascalABC.NET 4 05.04.2009 14:51
BETWEEN и LIKE одним запросом Pinya SQL, базы данных 9 19.08.2008 11:30