Факториал без цикла

1. scientes 288 07.11.22 17:13 Сейчас в теме
Встретилась задача о вычислении факториала числа без использования цикла. Для платформы 1С:Предприятие придумал следующий код. Какие еще есть варианты кроме рекурсии ?
Функция ФакториалБезЦикла(size=100) экспорт
	перем f;
	
	arr=new array(size);
	
	
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	//конвертация массива
	СериализаторXDTO.ЗаписатьXML(ЗаписьXML, arr);
	МассивСтр = ЗаписьXML.Закрыть();
	//превращаем массив в таблицу
	Шапка="<Array xmlns=""http://v8.1c.ru/8.1/data/core"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">";
	Замена="<ValueTable xmlns=""http://v8.1c.ru/8.1/data/core"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
	       |<column>
	       |<Name xsi:type=""xs:string"">N</Name>
		   |<ValueType>
		   |	<Type>xs:decimal</Type>
		   |	<NumberQualifiers>
		   |		<Digits>0</Digits>
		   |		<FractionDigits>0</FractionDigits>
		   |		<AllowedSign>Any</AllowedSign>
		   |	</NumberQualifiers>
		   |</ValueType>
	       |</column>";
	МассивСтр=СтрЗаменить(МассивСтр,Шапка,Замена); 
	Замена="<row>
		   |<Value xsi:type=""xs:decimal"">1</Value>
	       |</row>";
    МассивСтр=СтрЗаменить(МассивСтр,"<Value xsi:nil=""true""/>",Замена);
	МассивСтр=СтрЗаменить(МассивСтр,"Array","ValueTable");
	
	
	//Читаем таблицу значений из XML    
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(МассивСтр);
    тз = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
	
	Текст="ВЫБРАТЬ
	      |	vt.N КАК N,
	      |	АВТОНОМЕРЗАПИСИ() КАК j
	      |ПОМЕСТИТЬ T
	      |ИЗ
	      |	&Параметр КАК vt
	      |;
	      |
	      |////////////////////////////////////////////////////////////­////////////////////
	      |ВЫБРАТЬ
	      |	T.N КАК N,
	      |	T.j КАК j
	      |ИЗ
	      |	T КАК T";
	запрос=новый запрос(Текст);
	запрос.МенеджерВременныхТаблиц=новый МенеджерВременныхТаблиц;
	запрос.Параметры.Вставить("Параметр",тз);
	arr=запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("j");
	
	Выполнить("f="+СтрСоединить(arr,"*"));
	возврат f;
КонецФункции

Показать
По теме из базы знаний
Ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. Sashares 34 07.11.22 17:25 Сейчас в теме
(1)
АВТОНОМЕРЗАПИСИ() КАК j

Не обязательно будет начинаться с 1.
4. SlavaKron 07.11.22 17:35 Сейчас в теме
(1) Получить последовательность чисел можно проще через порождающий запрос https://infostart.ru/public/90367/
8. scientes 288 08.11.22 09:27 Сейчас в теме
(4) Да, для генерации можно воспользоваться этим решением. Цикл надо будет заменить на рекурсию.
9. Ivan_Sol 19 08.11.22 09:32 Сейчас в теме
(4)
&НаСервереБезКонтекста
Функция ФакториалБезЦикла(size=100) экспорт
    перем f;
	
	Если size = 0 Тогда
		Возврат 1;
	КонецЕсли;
	
    arr = new array(size);
    
	Запрос1 = Новый Запрос("
		|ВЫБРАТЬ
		|	0 КАК Х
		|ПОМЕСТИТЬ Регистр1
		|
		|ОБЪЕДИНИТЬ
		|
		|ВЫБРАТЬ
		|	1
		|;
		|
		|////////////////////////////////////////////////////////////­////////////////////
		|ВЫБРАТЬ
		|	Младшие.Х + 2 * Старшие.Х КАК Х
		|ПОМЕСТИТЬ Регистр2
		|ИЗ
		|	Регистр1 КАК Младшие,
		|	Регистр1 КАК Старшие
		|;
		|
		|////////////////////////////////////////////////////////////­////////////////////
		|ВЫБРАТЬ
		|	Младшие.Х + 4 * Старшие.Х КАК Х
		|ПОМЕСТИТЬ Регистр4
		|ИЗ
		|	Регистр2 КАК Младшие,
		|	Регистр2 КАК Старшие
		|;
		|
		|////////////////////////////////////////////////////////////­////////////////////
		|ВЫБРАТЬ ПЕРВЫЕ " + size + "
		|	Младшие.Х + 16 * Старшие.Х КАК Х
		|ИЗ
		|	Регистр4 КАК Младшие,
		|	Регистр4 КАК Старшие
		|ГДЕ
		|	Младшие.Х + 16 * Старшие.Х > 0
		|
		|УПОРЯДОЧИТЬ ПО
		|	Х");

	arr = Запрос1.Выполнить().Выгрузить().ВыгрузитьКолонку("Х");

	Выполнить("f="+СтрСоединить(arr,"*"));
    возврат f;
КонецФункции
Показать
11. beldieff 08.11.22 10:00 Сейчас в теме
(1)

Функция fuck(i)
	
	Если i <= 1 Тогда
		Возврат 1
	Иначе 
		Возврат i * fuck(i-1)
	КонецЕсли;
	
КонецФункции // fuck()
Показать
12. user1831019 08.11.22 10:07 Сейчас в теме
(11) Так это рекурсия. Можно сразу написать в одну строку.
Возврат (?(i<=1, 1, i * fuck(i-1)));
13. beldieff 08.11.22 10:09 Сейчас в теме
(12)
Можно сразу написать в одну строку.
Мне платят построчно;)
succub1_5; +1 Ответить
21. scientes 288 08.11.22 12:15 Сейчас в теме
(13)
(1) Надо использовать конструкцию Выполнить("f="+СтрЗаменить(СтрСоединить(arr,"*"),Символ(160),""));
3. dabu-dabu 289 07.11.22 17:27 Сейчас в теме
Формула Стирлинга позволяет посчитать приблизительное значение, актуальна при больших значениях
5. comptr 30 07.11.22 17:38 Сейчас в теме
Факториал = 1;
Множитель = 1;
	
~НачалоЦикла:
Факториал = Факториал * Множитель;
Множитель = Множитель + 1;

Если Множитель <= Цель Тогда
	Перейти ~НачалоЦикла;
КонецЕсли;
	
Сообщить(Факториал);
Показать
6. user856012 13 07.11.22 23:42 Сейчас в теме
(5) "Это и я так могу!" (с) Промокашка

В вашем коде нет оператора цикла, но сам цикл - есть. А автор вроде как поставил задачу "без использования цикла".

Как говорится "почувствуйте разницу", аналогичная тема: https://www.cyberforum.ru/turbo-pascal/thread86319.html

P.S. Можно гораздо проще, чем в (1), вот код (фрагмент):
Функция ФакториалБезЦикла(size=100) экспорт
Если size=1 Тогда
   Возврат 1;
ИначеЕсли size=2 Тогда
   Возврат 2;
ИначеЕсли size=3 Тогда
   Возврат 6;
ИначеЕсли size=4 Тогда
   Возврат 24;
ИначеЕсли size=5 Тогда
   Возврат 120;
ИначеЕсли size=6 Тогда
   Возврат 720;
ИначеЕсли size=7 Тогда
   Возврат 5040;
ИначеЕсли size=8 Тогда
   Возврат 40320;
ИначеЕсли size=9 Тогда
   Возврат 362880;
ИначеЕсли size=10 Тогда
   Возврат 3628800;
Показать

...и так далее. :-)
succub1_5; ingermax; beldieff; +3 Ответить
7. comptr 30 08.11.22 06:17 Сейчас в теме
(6)
В вашем коде нет оператора цикла, но сам цикл - есть.

Спасибо, кэп!

Можно гораздо проще, чем в (1), вот код (фрагмент):

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

Я всего лишь привёл код, подходящий под условия задачи, которые, обычно звучат как "не используя оператор цикла", так как ориентированы на изучающих язык. Думаю, что единственный вариант, строго подходящий под условия - рекурсия, остальные будут просто ухищрениями для обхода прямого использования оператора цикла путём перекладывания этой функции на внутренности платформы. Ведь "СтрЗаменить" и "запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("j");" сами по себе внутри платформы ещё как используют циклы.
14. ingermax 08.11.22 10:54 Сейчас в теме
(7) Какой переменной в 1С вы будете возвращать факториал ста? Или даже 20? В каких реальных задачах интерпрайза это может быть нужно? Так что код в (6) в реальной жизни и для реальных цифр не будет столь уж большим и страшным. А под любое число вы будете то там, то там натыкаться на различные ограничения.
15. user856012 13 08.11.22 11:13 Сейчас в теме
(14)
код в (5) в реальной жизни и для реальных цифр
Сама задача, поставленная автором, к реальной жизни не имеет никакого отношения: цикл является одной из базовых структур любого языка программирования и сознательный отказ от него - очередная попытка натянуть сову на глобус.
не будет столь уж большим и страшным
Для совы? Ой, не уверен в этом... ;-)
16. SlavaKron 08.11.22 11:32 Сейчас в теме
(14)
Какой переменной в 1С вы будете возвращать факториал ста?
Технически для 1С это не проблема, расчеты не ограничены разрядностью архитектуры.
19. starik-2005 3033 08.11.22 11:46 Сейчас в теме
(16) Если для платформы это несущественно, то для языка запросов уже все не так однозначно, а народ тут топит за язык запросов, почему-то считая, что SQL там циклы не крутит.
17. lmnlmn 69 08.11.22 11:39 Сейчас в теме
(7)
Думаю, что единственный вариант, строго подходящий под условия - рекурсия...
Есть желающие проверить глубину стека платформы?
18. starik-2005 3033 08.11.22 11:45 Сейчас в теме
(17) "1748" если память не изменяет.
20. lmnlmn 69 08.11.22 12:01 Сейчас в теме
(18) Не поленился. Файловая дала 636 рекурсивных вызовов сделать, но неизвестно что там у нее еще на стеке было окормя моей рекурсии.

P.S. Не знал что по переполнению стека 1С вываливает "Аварийное завершение" и все - попробуй найди.
22. starik-2005 3033 08.11.22 13:06 Сейчас в теме
(20)
попробуй найди
Мы в файл писали, каждый раз дописывая номер итерации (append). На 8.3.13+ было как раз 1700++ итераций (запомнилось, как "1748"). При том не зависело от количества и размера передаваемых параметров.
23. lmnlmn 69 08.11.22 13:19 Сейчас в теме
(22) Здесь-то ладно. А вот если в проде обход дерева или же XDTO какое-нибудь вылетит, то детективная вечеринка обеспечена.
24. starik-2005 3033 08.11.22 15:22 Сейчас в теме
(23)
обход дерева или же XDTO какое-нибудь вылетит, то
Что-то сомневаюсь я, что такие деревья существуют (даже 100+ вложений). Ни разу не сталкивался с проблемами рекурсивных алгоритмов, т.к. они подразумевают сравнительно небольшую степень вложенности (те же деревья или XDTO-пакеты, они же типы XML, если только зацикленные - был такой момент в XBRL-отчетности, поставил проверку на повторяемость вложения - достаточно было одного соответствия). Ну и при наличии циклической сцылки и нерекурсивный алгоритм зациклится, просто будет работать бесконечно, а рекурсия хоть вышибет программу. А тут уж не знаю, что лучше (хуже)...
10. beldieff 08.11.22 09:54 Сейчас в теме
Оставьте свое сообщение
Вакансии
Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)

Программист 1С
Москва
зарплата от 250 000 руб.
Полный день

Программист 1C
Волгоград
зарплата от 200 000 руб.
Полный день

Аналитик
Санкт-Петербург
зарплата от 200 000 руб. до 250 000 руб.
Полный день