|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Ускорение поиска числа факториала |
|
C/C++ - Ускорение поиска числа факториала
|
Старожил Сообщения: 222 |
Профиль | Отправить PM | Цитировать Люди помогите сделать бысрый алгоритм нахождения числа из его факториала.
Я писал вот такой код но он оч медленный #include <iostream.h> #include <fstream.h> int faknom(int a) { int i=1; while(a!=i) { a=a/i; i++; }; return i; }; int main() { int Nfak; ifstream fin("input.txt"); fin>>Nfak; fin.close(); ofstream fout("output.txt"); fout<<faknom(Nfak)<<endl; fout.close(); return 0; } Как ускорить алгоритм расчета? |
|
Отправлено: 13:00, 01-06-2008 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Цитата DaRiYs:
Цитата mrcnn:
Так вот, если ограничение всё-таки 64 кб, то спокойно можно сделать таблицу. (длина десятичной записи n!) -> значение n. Длина для всех факториалов начиная с 10! точно различна (для значений меньше можно использовать честный подбор). Длина 2000! - 5737. Элементарная программа на питоне (или любом другом языке, в котором встроена поддержка больших чисел) легко позволяет построить такую таблицу за пару минут. |
||
------- Отправлено: 17:26, 01-06-2008 | #21 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Старожил Сообщения: 222
|
Профиль | Отправить PM | Цитировать Ну так у меня ограничение кода до 4 кб. Эт не АСМ а ему подобный
|
------- Отправлено: 17:43, 01-06-2008 | #22 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Если очень хочется извратиться и впихнуть всё в 4кб, то можно закодировать таблицу в виде сдвигов между соседними значениями. Т.к. мы умножаем максимум на 2000, то длина изменяется не более, чем на 4 знака каждый раз; но не менее, чем на один. Для хранения этой информации достаточно 2 бит. А для хранения всех сдвигов - 4000 бит, которые можно записать в виде строки (если использовать только печатные символы из нижней половины ascii, чтобы можно было вставить в исходный текст без изменений) всего в 4000/log2(64)=667 символов, ещё 3кб на код останется . И потом декодировать оттуда нужную информацию небольшим кусочком кода.
Всё решение будет типа такого: unsigned char[] diff_table="blah-blah blah..."; //667 символов таблицы. // получить i-й сдвиг из таблицы. int getDiff(int i) { unsigned char c = diff_table[i/6] - 32; int diff = (c >> ((i%6)*2)) & 3; return diff; } // .... char fac_str[10000]; cin >> fac_str; // зачитываем факториал, _как строку_ int need_len = strlen(fac_str); // длина факториала, для которого надо найти n int n = 0; // ответ будет здесь if (need_len <= 8) { // n <= 10, тупо подбираем int facn = 1; int fac = atoi(fac_str); for (n = 1; facn < fac; ++n) { facn *= n; } } else { int len = 8; // длина факториала 10 // начинаем подбирать с 11 for (n = 11; len < need_len; ++n) { len += getDiff(n); } } |
------- Последний раз редактировалось ivank, 01-06-2008 в 19:19. Отправлено: 17:52, 01-06-2008 | #23 |
Новый участник Сообщения: 15
|
Профиль | Отправить PM | Цитировать Могу предложить еще вариант без длинной арифметики. Не знаю, будет ли он работать быстрее, поскольку там много вычислений с плавающей точкой... и влезет ли в нужный объем.
Правильно работать он будет, только если число в файле заведомо является факториалом. Способ: приближенное значение натурального логарифма факториала числа n равно ln(n!)=1/2(ln(2)+ln (Pi))+ln(n)+n*ln(n)-n десятичный логарифм равен Log(n!)=ln(n!)/ln(10) Количество знаков в факториале будет равно Log(n!)+1, округленному снизу. Считываем из файла факториал в виде символьной строки. Считаем количество знаков в этой строке. Дальше ищем на отрезке числовой оси (1;2000) нужное нам число n методом деления отрезка пополам. То есть, проверяем числа 1 и 2000 (считаем по формуле), если кол-ва цифр в их факториалах не подходят, берем число в середине отрезка (например 1000), считаем кол-во цифр в его факториале. Если опять не подходит, берем середину отрезка (1;1000) или (1000;2000)-- в зависимости от того, больше или меньше кол-во знаков в числе из файла, чем в 1000! Дальше снова, максимум за 10--12 шагов число n точно определяется И одна тонкость: для чисел, меньших 7, лучше сохранить факториалы в файле с программой, и сначала проверять не является ли n одним из этих чисел. после чего делить отрезок не от 1 до 2000, а от 7 до 2000. (потому, что факториалы разных чисел, меньших 7, могут иметь одинаковое кол-во знаков) |
------- Отправлено: 18:53, 01-06-2008 | #24 |
Старожил Сообщения: 222
|
Профиль | Отправить PM | Цитировать Мож хтонибудь всетаки напишет код на ассемблере для использования его в С++
|
------- Отправлено: 19:56, 01-06-2008 | #25 |
Ветеран Сообщения: 3320
|
Профиль | Отправить PM | Цитировать Цитата Drongo:
#include <Windows.h> #include <iostream> using namespace std; int main(int argc, char* argv[]) { SYSTEMTIME st; GetSystemTime(&st);//GetLocalTime() cout << "\n" <<st.wSecond << " " <<st.wMilliseconds; Sleep(1000); GetSystemTime(&st);//GetLocalTime() cout << "\n" <<st.wSecond << " " <<st.wMilliseconds; return 0; } Для данного примера разницы между GetSystemTime() и GetLocalTime() нет. А вообще первая возвращает время по Гринвичу UTC, вторая по выбранному свойствах системы часовому поясу. ivank, а как быть с iostream что б по стандарту? Или это » только в Linux, а micorosoft будет оставлять совместимость в своём компиляторе? cout удобние printf Или можно просто вывести значения st.wSecond и st.wMilliseconds через printf не усложняя код? Со строчкой printf("%s %s",st.wSecond, st.wMilliseconds); компилится, но во время выполнения ошибка естественно Цитата:
|
||
Отправлено: 19:57, 01-06-2008 | #26 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Admiral,
Цитата Admiral:
Цитата Admiral:
Цитата Admiral:
DaRiYs, за вас никто ничего писать не будет. Вам предложили методы решения задачи (целых 3). Если вы чётко объясните, что вас в них не устраивает (или что непонятно), то можно будет продолжать диалог. |
|||
------- Отправлено: 20:10, 01-06-2008 | #27 |
Ветеран Сообщения: 3320
|
Профиль | Отправить PM | Цитировать ivank, вопрос навеян этим постом, я об этом в предыдущем посте указал », когда сказал про Linux.
Да я понимаю, что строка printf("%s %s",st.wSecond, st.wMilliseconds); ошибочна. Я к примеру показал сравнения с cout << "\n" <<st.wSecond << " " <<st.wMilliseconds; которой кроме себя самой не нужно приведения типов, что б не вызывать ошибку при выполнении. Компилятор MS C++ 2008 Express прохлопал всё без Warnings, возможно по дефолтному уровню предупреждений не положено замечать эту строчку как потенциально опасной. Сам я использую в основном printf, но когда отлаживаю программу и ещё не знаю нужной функции приведения типов, использую cout, так как он их щёлкает как орешки и выводит мне нужное значение. Можно и Debug средствами среды узнавать значения переменных, но они не всегда доступны. |
Отправлено: 20:27, 01-06-2008 | #28 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Цитата Admiral:
|
|
------- Отправлено: 20:32, 01-06-2008 | #29 |
Ветеран Сообщения: 3320
|
Профиль | Отправить PM | Цитировать ivank, не прошло и дня.
printf("time %02u:%02u:%02u:%03u\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); и ни каких сout с #include <iostream> и using namespace std; а лишь printf c #include <stdio.h> нашёл здесь. |
Отправлено: 20:44, 01-06-2008 | #30 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Простые числа на Си++ | nemo555 | Программирование и базы данных | 13 | 13-03-2007 21:24 | |
*Теория* | Числа Фибоначчи | Grub | Программирование и базы данных | 8 | 28-07-2006 14:23 | |
четность числа | elfoflorien | Вебмастеру | 6 | 18-09-2005 20:49 | |
Случайные числа на JavaScript | Dimonweb | Вебмастеру | 2 | 12-08-2004 03:23 | |
суммироват числа | Artashes | Программирование и базы данных | 3 | 30-08-2003 18:31 |
|