What is an algebraic number? Any complex numbers which is root of a polynomial with integer coefficients $p(x) \in \mathbb{Z}[x]$, or in other words solution of $p(x)=0$
\[ a \in \bar{\mathbb{Q}} \Leftrightarrow \exists p \in \mathbb{Z}[x] \mid p(a)=0 \]
Obviously, this set includes the set of relative integers $\mathbb{Z}$ since every integer $n \in \mathbb{Z}$ is solution of $x - n = 0$
Non less obviously, it includes the set of rationals $\mathbb{Q}$ since every fraction $p/q \in \mathbb{Q}$ is solution of $q x - p = 0$
It also includes some irrational numbers like $\sqrt{2}$ which is solution of $x^2 - 2 = 0$
But it also includes some complex numbers like $\imath$ which is solution of $x^2 + 1 = 0$
$\bar{\mathbb{Q}}$ has the structure of a field with + and * operations,
but more than that, it is an algebraic closure, which means that the roots of polynomials in $\bar{\mathbb{Q}}[x]$ are in $\bar{\mathbb{Q}}$
(the roots of polynomials whose coefficients are algebraic numbers are also algebraic numbers)
That make it a very important algebraic structure.
An algebraic number can be easily represented on computers by a polynomial of which it is a root and a region of the complex plane containing this root (and only this root).
For the subset of real algebraic numbers $\mathbb{R} \cap \bar{\mathbb{Q}}$, this region can be reduced as an interval $[a,b]$ of the real axis sufficiently narrow so as to contain a single real root of the polynomial.
We have just defined the AlgebraicNumber introduced in Squeak in MathMorphs by the team of Leandro Caniglia in the late 90s.
As we saw, it should better have been named RealAlgebraicNumber or maybe just AlgebraicReal
The fun with such numbers is that arithmetic operations are exact.
They can be defined by operations on their polynomials (and intervals).
Since I just introduced the polynomials in Squeak, we can revisit this nice piece of code from MathMorph.
We can manipulate numbers like $\sqrt{5}$ exactly, without having to resort to a floating point approximation like 5 sqrt.
Of course, if you are not interested in learning mathematics, not annoyed that 5 sqrt squared is slightly greater than 5, but just needing a fast square root, stick with Float.
The AlgebraicNumber package ugraded for Squeak trunk is available at https://squeaksource.com/STEM.html
It will require Polynomials and its prereq IntegerFactorization and CollectionArithmetic.
I didn't set up a Metacello nor a Monticello configuration yet, maybe I will.
The implementation rely on two essential features:
- the Sturm algorithm for isolating the real roots of polynomials https://en.wikipedia.org/wiki/Sturm%27s_theorem
- the resultant of polynomials for performing arithmetic https://en.wikipedia.org/wiki/Resultant
In details, there is a bit more, Sturm requires squareFree polynomials. Also AlgebraicNumber uses irreducible (minimal) polynomials, and thus factor, otherwise arithmetic operations result in a explosion of degree.
In the tradition of Smalltalk-80, AlgebraicNumber extends Fraction so an AlgebraicNumber whose value is rational is automatically reduced to its Fraction or Integer value.
It thus has to be able to perform mixed arithmetic in a natural way.
Mixed arithmetic with Float will cancel the exactness of operations though and convert results to limited precision.
Like with Fraction, such operations are subject to double rounding: the AlgebraicNumber is first converted asFloat, then operation is performed in floating point.
There are two practical utilities for creating an AlgebraicNumber:
- taking the nth root of a fraction $\sqrt[n]{\frac{p}{q}}$,
sqr3 := AlgebraicNumber nthRoot: 2 of: 3. - compute $sin(\pi \frac{p}{q})$ and $cos(\pi \frac{p}{q})$,
sinPiOver3 := AlgebraicNumber sinpi: 1/3.
We can check $sin(\frac{\pi}{3}) = \frac{\sqrt{3}}{2}$,
Or perform some more elementary checks:
Or we could play with the golden ratio:
For example check the Binet formulation of fibonacci number $F_n$ :
Or we could also check one of the Ramanujan expressions involving radicals like
\[ \sqrt[3]{\frac{1}{9}}-\sqrt[3]{\frac{2}{9}}+\sqrt[3]{\frac{4}{9}} = \sqrt[3]{\sqrt[3]{2}-1} \]
Since not all algebraic number can be expressed by elementary operations +,-,*,/ and radicals,
the more general solution is to define them by a polynomial and the interval containing the root, like
Galois fields theory make it possible to predict if such algebraic number can be printed or not with radicals.
And in this case, it is also possible to find such expressions, though generally awfully long.
This simple AlgebraicNumber package is not equipped to find them.
This is why it will just print an approximation in decimal notation, based on the more or less refined interval.
In the case of our nonRadical the approximation is very rough:
No surprise, it is somewhere between 0 and 2 exactly as we asked for...
It is possible to force the refinement of the approximation, like:
and get
That's how an AlgebraicNumber is printed now.
Final notice: like polynomials, the code has not been generated by AI, if that really matters.