gifts2017

Вычисление формул в 1С через обратную польскую запись

Опубликовал BAZIL BAZIL (wbazil) в раздел Программирование - Практика программирования

Преобразование обычного выражения в постфиксную форму и вычисление значения формулы через стек.
Понадобилось рассчитывать формулы прямо из документа 1С, гугл в первых ссылках выдает алгоритм Дейкстры и обратную польскую запись. По нему и была решена поставленная задача.

 Тестировалось на:

Обычная запись ОПЗ Результат
2-1+3*4 21-34*+ 13
2-(1+3)*4 213+4*- -14
(2-(1+3)*4)*5 213+4*-5* -70
2-(1+3*4)*5 2134*+5*- -63

Работу с стеком и разбор строки прикладываю в обработке.

Привожу основные функции:

 

//преобразование в ОПЗ
	Пока лпСтрокаВход <> "" Цикл
		лпТокен = ТокенПолучить(лпСтрокаВход);
		лпТипТокена = ТокенТип(лпТокен);
		Если лпТипТокена = "Число" Тогда
			лпСтрокаВыход = лпСтрокаВыход + лпТокен + "!";
		КонецЕсли;
		Если лпТипТокена = "(" Тогда
			СтекДобавить(лпСтек, "(");
		КонецЕсли;
		Если лпТипТокена = ")" Тогда
			Пока СтекВершина(лпСтек) <> "(" Цикл
				лпВершина = СтекВершина(лпСтек);
				лпСтрокаВыход = лпСтрокаВыход + лпВершина + "!";
				СтекУдалить(лпСтек);
			КонецЦикла;
			СтекУдалить(лпСтек);
		КонецЕсли;
		Если лпТипТокена = "Функция" Тогда
			Пока (НЕ СтекПустой(лпСтек)) И (ДатьПриоритетОперации(лпТокен) >= ДатьПриоритетОперации(СтекВершина(лпСтек))) И СтекВершина(лпСтек) <> "("  Цикл
				лпСтрокаВыход = лпСтрокаВыход + СтекВершина(лпСтек) + "!";
				СтекУдалить(лпСтек);
			КонецЦикла;
			СтекДобавить(лпСтек, лпТокен);
		КонецЕсли;
		
		лпСтрокаВход = Сред(лпСтрокаВход, 2, 777);
	КонецЦикла;
	
	Пока НЕ СтекПустой(лпСтек) Цикл
		лпСтрокаВыход = лпСтрокаВыход + СтекВершина(лпСтек) + "!";
		СтекУдалить(лпСтек);
	КонецЦикла;
	
	пвПостфиксная = лпСтрокаВыход;
 
//вычисление через стек:
	лпТекс = СтрЗаменить(лпСтрокаВход, "!", Символы.ПС);
	Для Ит = 1 По СтрЧислоСтрок(лпТекс) Цикл
		лпТокен = СтрПолучитьСтроку(лпТекс, Ит);
		лпТипТокена = ТокенТип(лпТокен);
		Если лпТипТокена = "Число" Тогда
			СтекДобавить(лпСтек, Число(лпТокен));
		КонецЕсли;
		Если лпТипТокена = "Функция" Тогда
			лпОператор2 = СтекВершина(лпСтек);
			СтекУдалить(лпСтек);
			лпОператор1 = СтекВершина(лпСтек);
			СтекУдалить(лпСтек);
			Если лпТокен = "+" Тогда
				лпРезультат = лпОператор1 + лпОператор2;
			КонецЕсли;
			Если лпТокен = "-" Тогда
				лпРезультат = лпОператор1 - лпОператор2;
			КонецЕсли;
			Если лпТокен = "*" Тогда
				лпРезультат = лпОператор1 * лпОператор2;
			КонецЕсли;
			Если лпТокен = "/" Тогда
				лпРезультат = лпОператор1 / лпОператор2;
			КонецЕсли;
			СтекДобавить(лпСтек, лпРезультат);
		КонецЕсли;
	КонецЦикла;

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
МодульСтека
.epf 7,97Kb
08.07.15
3
.epf 1.0 7,97Kb 3 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Ivan Boychuk (IvanBoychuk123) 06.07.15 17:27
А чем функция Вычислить(<Выражение>) не подошла?
aexeel; baton_pk; vasyak319; +3 Ответить 1
2. Сергѣй Батанов (baton_pk) 06.07.15 20:29
я, конечно, люблю польские записи, всякую алгоритмику и прочее, но раз уж тут приведена исходная задача, то присоединюсь к (1).
3. BAZIL BAZIL (wbazil) 06.07.15 21:57
тем что это просто модель, а в реальной конфе все по другому но на основе этого модуля
PS приводить конфу смысла нет она специфическая
4. BAZIL BAZIL (wbazil) 06.07.15 22:03
если сообщество найдет формулу которая преобразовывается не корректно, буду благодарен, я конечно тестил, но через некоторое время в рабочую базу пойдет
лишняя проверка не помеха

заранее спасибо
5. Николай Крылов (Nikola23) 07.07.15 07:59
а зачем все это? в 1с памяти не хватает? Википедия пишет, что такая запись - необходимость оптимизации памяти, если речь идет о байтах.
6. BAZIL BAZIL (wbazil) 07.07.15 08:11
дело не в памяти, в общем задачу можно сформировать так:
нужно создать документ который сможет повторить формулы с excel, конвертацию валют, получение данных для расчета с внешней программы(не 1с).
7. Anton Loginchev (logos) 08.07.15 09:26
(6) wbazil, Терзают меня смутные сомнения, что делать сие на языке 1С - не самое быстрое решение. Таки транслятор кода модулей конфигурации очень медленный. Не думали о переносе этого функционала во внешнюю компоненту. Мне кажется скорость должна вырасти в разы, если не больше.
8. Two World (Prometeus2011) 08.07.15 13:00
9. BAZIL BAZIL (wbazil) 08.07.15 15:57
(7) так не спрашивают же, говорят надо
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа