C/C++ Порядок умножения матриц

В математике, если перемножить три матрицы «A», «B» и «C», так что четвертая матрица «D = A * B * C», то порядок должен быть вычислен справа налево. Используя круглые скобки для пояснения, предыдущее утверждение точно эквивалентно следующему; 'D = (А * (В * С))'.

Вы можете увидеть, как это применимо к выражению '{ M = A * B * C * D } == { M = (A * (B * (C * (D)))) }), которое является еще одним примером.

В C, C++ я провел тест с использованием деления, чтобы проверить порядок, в котором выполняются операции в C и C++.

Однако, вероятно, есть лучший способ сделать это, компилируя ассемблерный код:

float a = 1.0;
float b = 2.0;
float c = 2.0;
float ans = a / b / c;
printf("answer is %f\n", ans);

Это дает результат:

answer is 0.25

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

В математической библиотеке OpenGL, GLM, матричные операции вычисляются в правильном порядке, без скобок.

Как заставить operator*() вести себя таким образом?

Редактировать

Эээ, да, так что на самом деле это не имеет значения, как мне было указано. В таком случае у меня возникает вопрос, можно ли изменить порядок? (Может, я сонный?)


person FreelanceConsultant    schedule 18.07.2013    source источник
comment
Я думаю, что вы ошибаетесь насчет умножения матриц, оно на самом деле ассоциативно. ссылка на Википедию.   -  person Carl Norum    schedule 19.07.2013
comment
Да, но это непросто. Ищите шаблоны выражений: в основном храните дерево выражений и оценивайте его только при назначении, допуская произвольные преобразования дерева.   -  person Yakk - Adam Nevraumont    schedule 19.07.2013
comment
Чтобы сделать вопрос корректным, измените умножение матриц на векторное (перекрестное) произведение. Это неассоциативно, и существует гораздо больше формул a×(b×c), чем (a×b)×c, так что ассоциативность справа налево была бы естественной. Я бы, однако, не советовал полагаться на ассоциативность операторов, а использовать круглые скобки.   -  person Rainald62    schedule 08.08.2018


Ответы (2)


Оба оператора C++ / и бинарный * ассоциативны слева направо. Конец истории - это никак не изменить.

Умножение матриц является ассоциативным, так что это не должно влиять на вас .

person Carl Norum    schedule 18.07.2013

Причина проста: умножение матриц ассоциативно; скалярное деление нет. (A / (B / C)) не то же самое, что ((A / B) / C). Но (A * (B * C)) совпадает с ((A * B) * C) как для матричного, так и для скалярного умножения.

Таким образом, порядок, в котором С++ вызывает операторы, просто не имеет значения для умножения матриц.

person Nicol Bolas    schedule 18.07.2013
comment
Умножения C++ (и glsl) и умножение матриц НЕ являются ассоциативными, поскольку умножение операнда в другом порядке может изменить результаты из-за проблем с приближением и точностью. (A * (B * C)) совпадает с ((A * B) * C) в математике, но не в C++ и не в glsl. Более того, если C — вектор, а не матрица, два решения будут иметь разное количество умножений. - person Lorenzo Belli; 27.05.2016