¿Qué significa asociatividad de izquierda a derecha?


Estoy confundido acerca de la definición de asociatividad de izquierda a derecha y de derecha a izquierda. También los he visto llamados asociatividad de izquierda y asociatividad de derecha y me gustaría saber cuál corresponde a cuál.

Sé que se relaciona con el orden en que las operaciones con la misma precedencia se preforman, como en si a = x * y * z significa a = x * (y * z) o a = (x * y) * z. No se cuál es asociativa de izquierda a derecha y cuál es asociativa de derecha a izquierda.

I he intentado Googlearlo, pero todo lo que he sido capaz de encontrar es tablas de lo que la asociatividad de los diferentes operadores son en c++. Mirar todos los ejemplos me ha confundido más.

Lo que también me confunde aún más es que:

glm::vec4 transformedVector = translationMatrix * rotationMatrix * scaleMatrix * originalVector;

Preforma la multiplicación de la matriz de escala primero, seguida de la matriz de rotación seguida de la traducción. En este ejemplo las matrices son todas de tipo glm:: mat4 y los vectores son de tipo glm:: vec4. ¿Es esto de izquierda a derecha o ¿asociatividad de derecha a izquierda? ¿Es esto lo mismo que la multiplicación normal o la multiplicación de los tipos glm es diferente?

Author: Nicol Bolas, 2014-08-31

6 answers

Normalmente se lee de izquierda a derecha. Normalmente haces matemáticas de izquierda a derecha. Esto es asociatividad de izquierda a derecha y es más común.

La mayoría de la gente resolverá

x = 23 + 34 + 45

Agrupándolo

x = (23 + 34) + 45

Esto es asociatividad de izquierda a derecha. Puedes recordarlo porque lees y haces matemáticas de izquierda a derecha.

Para la suma en matemáticas no importa demasiado. Siempre obtienes el mismo resultado de cualquier manera. Esto es porque la adición es asociativo. Decir que una operación es asociativa significa de izquierda a derecha y de derecha a izquierda asociación son la misma cosa. Para la adición en la programación todavía importa debido a los desbordamientos y la aritmética de coma flotante (pero no lo hará para enteros de tamaño normal en cualquier lenguaje razonable), por lo que cuando tenga un error de 2 AM con números grandes y el uso frívolo de a+b y b+a, recuerde en qué orden ocurrió la adición.

En tu ejemplo:

glm::vec4 transformedVector = translationMatrix * rotationMatrix * scaleMatrix * originalVector

Usted conceptualmente chomp a través del lado derecho primero, ya que ahí es donde está la cosa que estás actuando. Sin embargo, en C++, * es normalmente asociativo de izquierda a derecha y no es posible anular este. glm puede manejar esto de varias maneras: puede acumular una caché de cosas para multiplicar esperando que llegue el vector final y luego hacer la multiplicación de derecha a izquierda. También puede (más probable) utilizar el teorema del álgebra que la multiplicación de matrices es completamente asociativo, y simplemente multiplique de izquierda a derecha, luego asegure al lector en la documentación que es lo mismo que pensar en ello de derecha a izquierda. Sin embargo, necesita entender la implementación porque como se discutió anteriormente importa de qué manera la implementación elige multiplicar los números de coma flotante juntos.

Para completar, considere la resta. ¿Qué es a - b - c? Aquí realmente importa si es izquierda o derecha asociativo. Por supuesto que en matemáticas lo definimos como b (a - b) - c, pero algún extraño lenguaje de programación podría preferir que la resta sea asociativa derecha, y tomar a - b - c para significar siempre a - (b - c). Es mejor que este lenguaje alienígena tenga una página de documentación que especifique que - es correcto-asociativo, porque es parte de la especificación de la operación, no algo que se puede decir simplemente mirando el uso del operador.

 22
Author: djechlin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:10

Puedes verlo en las siguientes palabras:

Cuando combinamos operadores para formar expresiones, el orden en el que los operadores que se van a aplicar pueden no ser obvios. Por ejemplo, a + b + c puede ser interpretada como ((a + b) + c) o como (a + (b + c)). Decimos que + es izquierda-asociativa si los operandos se agrupan a la izquierda derecho como en ((a + b) + c). Decimos que es correcto-asociativo si agrupa operandos en la dirección opuesta, como en (a +(b + c)).

A. V. Aho & J. D. Ullman 1977, p. 47

 6
Author: thuzhf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-07 11:10:55

La respuesta más simple y más no tl;dr encontré:

En la mayoría de los lenguajes de programación, los operadores de suma, resta, multiplicación y división son asociativos a la izquierda, mientras que los operadores de asignación, condicional y exponenciación son asociativos a la derecha.

Gracias a: http://www.computerhope.com/jargon/a/assooper.htm

 3
Author: killjoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-22 15:46:08

a = (x * y) * z es de izquierda a derecha y a = x * (y * z) es de derecha a izquierda.

La multiplicación matricial de Glm asocia de izquierda a derecha porque sobrecarga el operador *. La cuestión aquí es sobre el significado de las multiplicaciones matriciales en términos de transformaciones geométricas, en lugar de la asociatividad matemática.

 2
Author: Code-Apprentice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-31 05:43:07

Un operador infijo (o más generalmente un tipo de expresión que tiene subexpresiones izquierda y derecha no cerradas) es asociativo a la izquierda si en el uso anidado de este operador (tipo de expresión) sin paréntesis explícitos, los paréntesis implícitos se colocan a la izquierda. Dado que * es asociativo a la izquierda en C++, a*b*c significa (a*b)*c. En caso de anidamiento más profundo, se produce un grupo de paréntesis implícitos en el extremo izquierdo: (((a*b)*c)*d)*e.

Equivalentemente esto significa la regla de producción sintáctica para este operador es izquierda-recursiva (lo que significa que la subexpresión izquierda tiene la misma categoría sintáctica para la que esta regla es una producción, de modo que la misma regla (mismo operador) se puede usar directamente para formar esa subexpresión; la subexpresión en el otro extremo tiene una categoría sintáctica más restrictiva, y usar el mismo operador allí requeriría paréntesis explícitos). En C++, una producción para expresión multiplicativa (sección 5.6 en el Estándar) dice expresión-mutliplicativa * pm-expression , con multiplicative-expression a la izquierda.

En consecuencia, en un uso anidado sin paréntesis explícitos, el operador más a la izquierda toma a sus vecinos inmediatos como operandos, mientras que las otras instancias toman como operando izquierdo el (resultado de) la expresión formada por todo a su izquierda.

Lo admito, he estado empujando esto un poco (demasiado lejos). Mi punto en que en ninguna parte de arriba hace la palabra " derecho" la asociatividad es una materia sintáctica y, por lo tanto, estática. Es importante dónde van los paréntesis implícitos, no en qué orden los escribe (de hecho no lo hace en absoluto, o de lo contrario serían explícitos). Por supuesto, para la asociatividad derecha, simplemente reemplace cada "izquierda" por "derecha" arriba.

En conclusión, no puedo ver ninguna razón válida por la que uno deba llamar a esta asociatividad (o agrupación) de izquierda a derecha, pero el hecho es que la gente lo hace (incluso el Estándar lo hace, aunque es perfectamente redundante dado que también se dan reglas de sintaxis explícitas).

La confusión proviene de explicar esto, como se hace a menudo, diciendo que (en ausencia de paréntesis explícitos) los operadores se realizan de izquierda a derecha (respectivamente de derecha a izquierda para operadores asociativos de derecha). Esto es engañoso porque confunde sintaxis con semántica (ejecución), y también solo es válido para operaciones con evaluación bottom-up (todos los operandos son evaluado antes que el operador). Para los operadores con reglas de evaluación especiales es simplemente incorrecto. Para los operadores && (y) y || (o) la semántica es evaluar el operando izquierdo primero, luego el operador mismo (es decir, decidir si el operando izquierdo o el operando derecho producirá el resultado) seguido posiblemente por la evaluación del operando derecho. Esta evaluación de izquierda a derecha es totalmente independiente de la asociatividad: los operadores resultan ser asociativos de izquierda, probablemente debido a que todos los operadores binarios no asignados son, pero (c1 && c2) && c3 (con paréntesis redundantes donde ya estarían implícitamente) tiene una ejecución equivalente a c1 && (c2 && c3) (es decir, ejecutar las condiciones de izquierda a derecha hasta que uno devuelve false y devuelve eso, o si ninguno devuelve true), y no puedo imaginar un compilador razonable generando código diferente para los dos casos. En realidad, encuentro que la agrupación correcta es más sugerente de cómo se evalúa la expresión, pero realmente no hace ninguna diferencia; lo mismo ocurre con or.

Esto es aún más claro para el operador condicional (ternario) ? ... :. Aquí se aplica la asociatividad, porque hay subexpresiones abiertas en ambos lados(cf. mi oración inicial); el operando medio está encerrado entre ? y : y nunca requiere paréntesis adicionales. De hecho, este operador se declara correcto - asociativo, lo que significa que c1 ? x : c2 ? y : z debe leerse como c1 ? x : (c2 ? y : z) en lugar de como (c1 ? x : c2) ? y : z (los paréntesis implícitos son derecho). Sin embargo, con los paréntesis implícitos los dos operadores ternarios se ejecutan de izquierda a derecha; la explicación es que la semántica del operador ternario no evalúa todas las subexpresiones primero.


Volviendo al ejemplo de tu pregunta, la asociatividad de izquierda (o agrupación de izquierda a derecha) significa que tu producto matriz-vector se analiza como ((M1*M2)*M3)*v. Aunque matemáticamente equivalente, es virtualmente imposible que esto se ejecute como M1*(M2*(M3*v)), incluso aunque eso es más eficiente. La razón es que la multiplicación de punto flotante no es verdaderamente asociativa (solo aproximadamente), ni por lo tanto es la multiplicación de matriz de punto flotante; el compilador por lo tanto no puede transformar una expresión en la otra. Tenga en cuenta que en ((M1*M2)*M3)*v no se puede decir cuál de las matrices se aplica primero a un vector, porque ninguna de ellas es: la matriz de los mapas lineales compuestos se calcula primero, y la que matriz se aplica a la matriz vector. El resultado será aproximadamente igual al de M1*(M2*(M3*v)) en el que se aplica M3, luego M2 y finalmente M1. Pero si quieres que las cosas sucedan así, tienes que escribir esos paréntesis.

 2
Author: Marc van Leeuwen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-14 10:59:47

La asociatividad de izquierda a derecha de un operador significa lado derecho del operador no debe tener ningún operador de mayor precedece( prioridad), pero se puede ser de la misma prioridad. Si hay algún operador de mayor prioridad en el lado derecho de nuestro operador, entonces tenemos que resolverlo primero.ejemplo:

x = 2 + 3 * 3;

Aquí, para el operador + (asociatividad de izquierda a derecha), el lado derecho contiene un operador *, que es de mayor prioridad que + operador, por lo que tenemos para resolverlo primero.

x = 2 + 9;
x = 11;

introduzca la descripción de la imagen aquí

introduzca la descripción de la imagen aquí

introduzca la descripción de la imagen aquí

 -1
Author: praveen chaudhary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-13 08:00:57