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

1. scientes 290 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 35 07.11.22 17:25 Сейчас в теме
(1)
АВТОНОМЕРЗАПИСИ() КАК j

Не обязательно будет начинаться с 1.
4. SlavaKron 07.11.22 17:35 Сейчас в теме
(1) Получить последовательность чисел можно проще через порождающий запрос https://infostart.ru/public/90367/
8. scientes 290 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 290 08.11.22 12:15 Сейчас в теме
(13)
(1) Надо использовать конструкцию Выполнить("f="+СтрЗаменить(СтрСоединить(arr,"*"),Символ(160),""));
3. dabu-dabu 298 07.11.22 17:27 Сейчас в теме
Формула Стирлинга позволяет посчитать приблизительное значение, актуальна при больших значениях
5. comptr 34 07.11.22 17:38 Сейчас в теме
Факториал = 1;
Множитель = 1;
	
~НачалоЦикла:
Факториал = Факториал * Множитель;
Множитель = Множитель + 1;

Если Множитель <= Цель Тогда
	Перейти ~НачалоЦикла;
КонецЕсли;
	
Сообщить(Факториал);
Показать
6. user856012 14 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 34 08.11.22 06:17 Сейчас в теме
(6)
В вашем коде нет оператора цикла, но сам цикл - есть.

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

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

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

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

P.S. Не знал что по переполнению стека 1С вываливает "Аварийное завершение" и все - попробуй найди.
22. starik-2005 3060 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 3060 08.11.22 15:22 Сейчас в теме
(23)
обход дерева или же XDTO какое-нибудь вылетит, то
Что-то сомневаюсь я, что такие деревья существуют (даже 100+ вложений). Ни разу не сталкивался с проблемами рекурсивных алгоритмов, т.к. они подразумевают сравнительно небольшую степень вложенности (те же деревья или XDTO-пакеты, они же типы XML, если только зацикленные - был такой момент в XBRL-отчетности, поставил проверку на повторяемость вложения - достаточно было одного соответствия). Ну и при наличии циклической сцылки и нерекурсивный алгоритм зациклится, просто будет работать бесконечно, а рекурсия хоть вышибет программу. А тут уж не знаю, что лучше (хуже)...
10. beldieff 08.11.22 09:54 Сейчас в теме
25. Kuzmin_A 13.06.24 11:53 Сейчас в теме
Если требуется часто получать, то лучше регистр сведений.
измерение - аргумент, ресурс - значение, или несколько ресурсов для разбивки по разрядам, например, 10^12 и 10^18.
разово заполнить до какого-то значения, далее для вычисления получать из регистра запросом.
Если в регистре отсутствует, то в фоновом выполнять процедуру расчета, брать ближайший аргумент и умножать (или делить, если ближайший аргумент выше) в цикле или деревом, в клиентском подключить ожидание.

Например,как в фоновом рассчитать <<тут>>
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот