Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: факториал миллиона.  (Прочитано 13015 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Chuda
Гость
« : 12-08-2006 21:49 » 

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

программа на питоне:
Код:
def factorial(n):
if n <= 1:
return 1;
return n*factorial(n-1);

print factorial(1000000);
Результат:
RuntimeError: maximum recursion depth exceeded
и такой результат при попытке высчитать факториал тысячи и более. 999 считает мгновенно.
попробовали различные калькуляторы - результат ещё хуже. считают по сотне-другой. самый лучший считает 1754!
виндовый штатный скрипнул, сказал, что считать будет долго, но взялся. и через каждые две минуты прерывает расчёты на ворчание о том, что задачу ему дали непосильную. А поскольку хотели измерить скорость вычисления, то такая работа не катит.
Вот простейшая программка на С:
Код:
#include <stdio.h>

int factorial(int n){
if(n <= 1)
return 1;
return n*factorial(n-1);
}
int main(){
printf("%d",factorial(1000000));
}
она готова считать факториал 15000, но миллион - нет, segmentation fault.

Так чем же можно его вычислить?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 13-08-2006 07:44 » 

Почитай вот темку:
https://forum.shelek.ru/index.php/topic,3805.0.html

Используй LISP Улыбаюсь

P.S. Хотя врядли ты его получишь в обозримое время. Да и ещё подумать надо, сколько такое число потребует памяти.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 13-08-2006 07:48 » 

Цитата: Chuda
она готова считать факториал 15000, но миллион - нет, segmentation fault.
Кстати, этого не может быть, потому что не может быть никогда.

Факторил 15000 гораздо больше MAX_INT. Просто такая программа систематически теряет старшие разряды числа при умножении. А ошибку получаешь возможно из-за переполнения стека рекурсивных вызовов. В Python программе это явно указано.
« Последнее редактирование: 13-08-2006 07:50 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 13-08-2006 07:54 » 

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

Ещё в Java есть тип BigInt неограниченного размера - можешь пробовать с ним. Он не даст потеряться старшим разрядам, если хватит памяти машины. Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 13-08-2006 08:39 » 

Кстати, хочу напомнить, что тема о больших числах есть - надо только уметь искать.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 13-08-2006 08:57 » 

Для больших N есть формула примерного значения факториала

N! ~ SqRt(2 * PI * N) * N^N / Exp(N)
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Chuda
Гость
« Ответ #6 : 13-08-2006 10:02 » 

На самом деле нет никакой практической надобности в вычислении этого числа. А поскольку нет такого типа данных, в который бы уместился результат, вот сижу сейчас и изобретаю. После того, как изобрету, посмотрю, кто и как это делал до меня.
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 14-08-2006 11:10 » 

Двоичный логарифм факториала миллиона ~ 20 миллионов.  Поэтому, при проектировании необходимо учитывать, что результат перемножения должен занимать порядка 20 мегабайт, и в распечатке результата будет порядка 6 миллионов десятичных цифр.
« Последнее редактирование: 14-08-2006 11:27 от npak » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Chuda
Гость
« Ответ #8 : 14-08-2006 11:24 » 

это не удивляет))))
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 14-08-2006 12:27 » new

В общем, проблема видится в двоичном представлении чисел. Хранение больших целых чисел "типовое" - хранятся в битовых сегментах как цифры системы счисления с большим основанием. Каждый сегмент кратен машинному слову для текущей архитектуры - 8, 16, 32, 64 и т.д. бит. Каждого сегмент должен иметь запас битов для умножения и сложения с переполнением.

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

Если решать целенаправленно задачу получения факториала миллиона на заранее выделенном куске памяти, то программирование расчёта на ассемблере при выборе сегмента числа равным разрядности процессора и при десятичном основании на 2ГГц Атлоне дало 10000! за 3 секунды, 50000! за 25 секунд, 160000! примерно за 5 минут. В общем, если это экстраполировать по экспоненте, получается, что за несколько часов сосчитается.  Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines