The quaternion number system extends the complex numbers1. Quaternions were first described by the Irish mathematician William Rowan Hamilton2 in 1843 and applied to mechanics in three-dimensional space. The symbol $$\mathbb{H}$$ for the set of all quaternions is a reference to his name. Just as complex numbers are a two-dimensional extension of the real numbers, quaternions are a two-dimensional extension of the complex numbers and thus a four-dimensional extension of the real numbers.
Quaternions are used in computer programs to describe three-dimensional rotations, such as in space travel to connect two spacecraft, in the automotive industry to use computer vision3 for controlling the movements of robot arms, in physical chemistry to analyze crystallographic textures4 and in three-dimensional computer games5. This works much better than Euler angles6 (yaw, pitch and roll) because small changes of orientation always lead to small changes in the four coordinates of quaternions, where Euler angles may suddenly jump from 359° to 1°, resulting in all sorts of computational problems.
A quaternion is an expression of the form
$$q = a + bi + cj + dk$$
where $$a$$, $$b$$, $$c$$ and $$d$$ are real numbers and where in addition to the units $$1$$ and the imaginary unit $$i$$ that are already known from complex numbers, and for which holds that
$$1^2 = 1, 1i = i1 = i, i^2 = -1$$
two more units $$j$$ and $$k$$ occur that satisfy the relations
$$j^2 = k^2 = ijk = -1$$
$$1j = j1 = j$$
$$1k = k1 = k$$
$$ij = -ji = k$$
$$jk = -kj = i$$
$$ki = -ik = j$$
As with complex numbers, a norm $$|q|$$ can be assigned to a quaternion $$q$$
$$|q| = \sqrt{a^2 + b^2 + c^2 + d^2}$$
The addition of two quaternions $$q_1 = a_1 + b_1i + c_1j + d_1k$$ and $$q_2 = a_2 + b_2i + c_2j + d_2k$$ is defined componentwise
$$\begin{align} q_1 + q_2 & = (a_1 + b_1i + c_1j + d_1k) + (a_2 + b_2i + c_2j + d_2k) \\ & = (a_1 + a_2) + (b_1 + b_2)i + (c_1 + c_2)j + (d_1 + d_2)k \end{align}$$
The addition is both commutative and associative. The multiplication is distributive over the addition. This means that the product of the sum of the terms is equal to the sum of the products of the individual terms. The product of two quaternions $$q_1$$ and $$q_2$$ can thus be calculated termwise in the usual way
$$\begin{align} q_1 q_2 & = (a_1 + b_1i + c_1j + d_1k)(a_2 + b_2i + c_2j + d_2k) \\ & = (a_1a_2 - b_1b_2 - c_1c_2 - d_1d_2) \\ & + (a_1b_2 + b_1a_2 + c_1d_2 - d_1c_2)i \\ & + (a_1c_2 - b_1d_2 + c_1a_2 + d_1b_2)j \\ & + (a_1d_2 + b_1c_2 - c_1b_2 + d_1a_2)k \end{align}$$
Since the units are commutative under the multiplication with the real numbers, but not with each other, the multiplication is not commutative. For example, it holds that
$$ij = k \neq ji = -k$$
Define a class Quaternion that can be used to represent quaternions. Four integers (int) can be passed to parameters a, b, c and d when creating a quaternion (Quaternion). Each parameter that is not explicity passed an argument takes the value 0 (zero).
A quaternion $$q$$ (Quaternion) must have a methode norm that takes no arguments and returns the norm $$|q|$$ (float).
If a quaternion $$q$$ (Quaternion) is passed to the built-in function str, a string representation (str) of $$q$$ must be returned that reads as a ± bi ± cj ± dk. The placeholder a is filled in with the parameter a of $$q$$, which is preceded by a minus sign if that parameter is negative. The placeholders b, c and d are filled in with the absolute values of the parameters b, c and d of $$q$$. Wherever there is a ± sign in the template, comes a minus sign (-) if the subsequent parameter is negative, or a plus sign (+) otherwise.
If a quaternion $$q$$ (Quaternion) is passed to the built-in function repr, a string representation (str) of $$q$$ must be returned that reads as a Python expression to create a new quaternion (Quaternion) with the same parameter values as $$q$$. The four arguments must be passed explicitly and positionally.
Make sure the binary operators for the addition (+) and the multiplication (*) always produce a new quaternion (Quaternion) if both operands are quaternions (Quaternion) or if one of the operands is a quaternion (Quaternion) and the other is an integer (int). When calculating the sum and the product of a quaternion and an integer $$m$$ (int), $$m$$ behaves like a quaternion with $$a = m$$ and $$b = c = d = 0$$.
>>> q1 = Quaternion(2, 4, 7, 3)
>>> q1.norm()
8.831760866327848
>>> print(q1)
2 + 4i + 7j + 3k
>>> q1
Quaternion(2, 4, 7, 3)
>>> q2 = Quaternion(a=-5, c=2, d=-4)
>>> q2.norm()
6.708203932499369
>>> print(q2)
-5 + 0i + 2j - 4k
>>> q2
Quaternion(-5, 0, 2, -4)
>>> q1 + q2
Quaternion(-3, 4, 9, -1)
>>> q2 + q1
Quaternion(-3, 4, 9, -1)
>>> q1 + 3
Quaternion(5, 4, 7, 3)
>>> 3 + q1
Quaternion(5, 4, 7, 3)
>>> q1 * q2
Quaternion(-12, -54, -15, -15)
>>> q2 * q1
Quaternion(-12, 14, -47, -31)
>>> q1 * 3
Quaternion(6, 12, 21, 9)
>>> 3 * q1
Quaternion(6, 12, 21, 9)