Разместите в теле модуля нижеприведенные функции.
Предварительно подготовьте две числовые мартрицы с типом значения ТаблицаЗначений (условно А и В). Либо программно, либо на форме с помощью элементов управления ТабличноеПоле. Имена колонок могут быть любыми. Размерности таблиц должны удовлетворять условию А(n x m) , В(m x k).
Осуществите вызов функции ПроизведениеМатриц(А, Б).
В результате будет получена таблица произведения двух матриц С(n x k). Результат можно загрузить в ТабличноеПоле, как и показано на рисунке.
Область практического применения может быть различной:
начиная от вспомогательного инструмента для обучения студентов, и кончая наглядными экономическими расчетами.
Функция ПодготовитьИсходнуюТаблицу(ТЗ, Литера)
ИсходнаяТ = ТЗ.Скопировать();
ш = 1;
Для каждого Колонка Из ИсходнаяТ.Колонки Цикл Колонка.Имя = "elem" + ш; ш = ш + 1; КонецЦикла;
ИсходнаяТ.Колонки.Добавить("i", Новый ОписаниеТипов("Число", , ,Новый КвалификаторыЧисла(12,0)));
ш = 1;
Для каждого Стр Из ИсходнаяТ Цикл Стр.i = ш; ш = ш + 1; КонецЦикла;
Возврат ИсходнаяТ
КонецФункции
Функция ПолучитьЗапросДекомпозиция(м, Литера)
ЗапросДекомпозиция = "//";
Для ш = 1 По м Цикл
ЗапросДекомпозиция = ЗапросДекомпозиция + " Объединить все
|ВЫБРАТЬ Таб.i как i, "+ш+" как j, Таб.elem"+ш+" как elem
|"+?(ш=1, "Поместить Таб", "")+"
| ИЗ Исходная"+Литера+" КАК Таб
|";
КонецЦикла;
ЗапросДекомпозиция = СтрЗаменить(ЗапросДекомпозиция, "Таб", "Таб"+Литера);
ЗапросДекомпозиция = СтрЗаменить(ЗапросДекомпозиция, "// Объединить все", "") +";";
Возврат ЗапросДекомпозиция
КонецФункции // ()
Функция ПолучитьЗапросКомпозиция(м)
ЗапросКомпозицияСоединения = ""; ЗапросКомпозицияПоля = ""; ЗапросКомпозиция = "";
ЗапросНумерацияСтрок = "Выбрать ИсходнаяА.i Поместить НумерацияСтрок Из ИсходнаяА как ИсходнаяА;";
Для ш = 1 По м Цикл
ЗапросКомпозицияПоля = ЗапросКомпозицияПоля + ", РезультатТаблица"+ш+".c как c" +ш;
ЗапросКомпозицияСоединения = ЗапросКомпозицияСоединения + "
|Левое Соединение РезультатТаблица как РезультатТаблица"+ш+" По РезультатТаблица"+ш+".j = "+ш+" И РезультатТаблица"+ш+".i = НумерацияСтрок.i";
КонецЦикла;
ЗапросКомпозиция = " Выбрать " + ЗапросКомпозицияПоля+ " Из НумерацияСтрок Как НумерацияСтрок " + ЗапросКомпозицияСоединения;
Возврат ЗапросНумерацияСтрок + СтрЗаменить(ЗапросКомпозиция,"Выбрать ,", "Выбрать ")
КонецФункции // ()
Функция ПроизведениеМатриц(ТабА, ТабБ)
мА = ТабА.Колонки.Количество(); мБ = ТабБ.Колонки.Количество();
Если Не мА = ТабБ.Количество() Тогда
Сообщить("Неверные размерности матриц!", СтатусСообщения.Важное); Возврат Неопределено;
КонецЕсли;
Запрос = Новый Запрос;
ЗапросТекст = //Исходные матрицы с колонкой с нумерацией строк
"ВЫБРАТЬ * ПОМЕСТИТЬ ИсходнаяА ИЗ &ТабА КАК ТабА; ВЫБРАТЬ * ПОМЕСТИТЬ ИсходнаяБ ИЗ &ТабБ КАК ТабБ;";
//Разбор матрицы
ЗапросТекст = ЗапросТекст + ПолучитьЗапросДекомпозиция(мА, "А") + ПолучитьЗапросДекомпозиция(мБ, "Б");
//Умножение
ЗапросТекст = ЗапросТекст +
"ВЫБРАТЬ ТабА.i КАК i, ТабБ.j КАК j, СУММА(ТабА.elem * ТабБ.elem) КАК c
|Поместить РезультатТаблица
|ИЗ ТабА КАК ТабА ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТабБ КАК ТабБ ПО ТабА.j = ТабБ.i
|СГРУППИРОВАТЬ ПО ТабА.i, ТабБ.j; ";
//Сбор матрицы
Запрос.Текст = ЗапросТекст + ПолучитьЗапросКомпозиция(мБ);
Запрос.УстановитьПараметр("ТабА", ПодготовитьИсходнуюТаблицу(T1, "а"));
Запрос.УстановитьПараметр("ТабБ", ПодготовитьИсходнуюТаблицу(T2, "б"));
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции // ()
На данный момент вопрос быстродействия не исследовался.
Качественное решение непростой задачи. Но я не совсем согласен с самой идеей использования таблиц значений для работы с матрицами. Таблица значений «заточены» под работу со строками-записями. И рано или поздно это даст о себе знать. В том числе и при вводе и выводе. Матрицы лучше хранить и обрабатывать в виде, получаемом в Вашем случае после функции «декомпозиции», убрав нулевые значения.
(1) ildarovich, спасибо!
Да, я понял, что хранить и обрабатывать так будет удобно. Тут как раз-таки проблемки с вводом-выводом имеются. А как иначе, если нужно допустим вручную вводить значения да еще чтобы это выглядело привычно?
Полагаю, только для матриц большой размерности это будет играть роль в плане быстродействия.
само умножение конечно выглядит элегантно)
а вот по поводу ввода матрицы в запрос, советую использовать подготовленную на встроенном языке таблицу значений. Что-то вроде:
Для Строка=0 По ИсходнаяТаблица.Количество() Цикл
Для Столбец=0 По ИсходнаяТаблица.Колонки.Количество() Цикл
новСтрока = ТаблицаЗапроса.Добавить();
новСтрока.i = Строка;
новСтрока.j = Столбец;
новСтрока.Значение = ИсходнаяТаблица[i][j];
КонецЦикла
КонецЦикла
а затем работать в запросе с «уплощенной» таблицей. На собственном опыте убедился что объединение большого количества подзапросов очень медленно работает. Например, в УПП, запрос к табличной части документа «Табель учета рабочего времени» работает в несколько раз медленнее (объединение 120 таблиц), чем запрос к подготовленной таблице значений.
(3) Synoecium,
Тут вроде это не особо критично, так как всего (м) таблиц объединяется.
Хотя, в конкретных приложениях, может так и следует поступить. Спасибо!