Complex Numbers in STACK
Complex numbers, especially the display of complex numbers, is a surprisingly subtle issue. This is because there is some genuine ambiguity in whether is a single object or the sum of two parts. In mathematics we use this ambiguity to our advantage, but in online assesment we need to be more precise. There are also issues of unary minus, e.g. not displaying . Similarly we typically do not display numbers like , unless of course we want to at which point we need the option to do so!
The general rules when displaying a complex number in Cartesian form "" are
- the real part should always appear to the left of the imaginary part;
- (or whatever symbol is being used for the imaginary unit) should appear on the right of its coefficient if and only if the coefficient is a numerical value. By numerical value, we mean something like but not things like , even if is a constant.
3+2*%ishould display as .
3-%ishould display as .
-a+b*%ishould display as .
-b*%ishould display as (not normally as ).
STACK provides two functions, one which simplifies and one which does not.
display_complex(ex)takes an expression
exand tries to display this as a complex number obeying the above rules. In particular, this function makes use of Maxima's
imagpartfunction to split up
exinto real and imaginary parts. To do this it must assume
simp:true, and so the real and imaginary part will be simplified. For example,
display_complex(1+2*%i/sqrt(2))is displayed as . If you really want then you will need to use the non-simplifying alternative below. This function respects normal conventions, e.g. when
realpartreturns zero this function will not print , it just prints , etc.
ais the real part and
bis the imaginary part (no checking is done). This function (mostly) does not simplify its arguments. So
disp_complex(0, 2)will appear as ;
disp_complex(2/4, 1)will appear as ; and
disp_complex(2, 2/sqrt(2))will appear as . Use the atom
nullif you do not want to print a zero for the real part, or print one times the imaginary part.
disp_complex(null, 2)will appear as and
disp_complex(null, null)will appear as just . Think of
nullas a non-printable unit (additive or multiplicative).
There is one exception. In order to pull out a unary minus to the front,
disp_complex(a, b) will simplify
b is not a number and it contains a unary minus. So, for example
disp_complex(a, (-b^2)/b) is displayed . (We might be able to fix this but this edge case requires disproportionate effort: ask the developers if this is essential).
You cannot use these functions to display complex numbers in this form , both these function will always display as .
Display respects the multiplication sign used elsewhere within expressions, so that you may have rather than .
Note that the function
display_complex(ex) returns the inert form
disp_complex(a, b). The expression
disp_complex(a, b) is an "inert form", which is only used to fine-tune the display. This function is not actually defined and so Maxima always returns it unevaluated. To remove the intert form from an expression, which is needed to manipulate this further, use
remove_disp_complex, e.g., with the following.
p1:disp_complex(a, b); p2:ev(p1, disp_complex=remove_disp_complex);
null has two different meanings within an expression it isn't sufficient to just define
disp_complex(ex1, ex2) := ex1+ex2*%i.)
There are occasions when you will need to explicitly add brackets to the displayed form of a complex number, e.g. to emphasise it is a single entity. To add brackets there is a further "inert form"
disp_parens which does nothing but add parentheses when the expression is displayed with the
tex() function. For example,
will display as . To remove these inert forms evaluate
p2:ev(p1, disp_complex=remove_disp_complex, disp_parens=lambda([ex],ex));
You must remove inert forms before expressions are evaluated by the potential response tree, for example in the feedback variables. For example,
disp_complex(a, b) is not algebraically equivalent to
A complex number written as is in polar form. The Maxima function
polarform re-writes a complex number in this form, however with
simp:false it does not simplfy the expressions for the modulus or argument (in STACK). Attempting to re-simplify the expression only returns the number to Cartesian form!
As a minimal example, try the following.
simp:false; p1:polarform(1+%i); p2:ev(polarform(1+%i), simp); p3:ev(p2, simp);
First we have
p1 is . Of course, we really need some simplification of the and the values.
Notice the difference between
p2: , and
p3: (which of course is not even either!).
The problem is that in this case
ev( ... , simp) is not idempotent, (i.e. in all cases) and the PHP-maxima connection inevitibly passes an expression to and from Maxima multiple times. If
simp:true then we get multiple simplifications, in this example back to
polarform_simp to rewrite the expression in polar form, and do some basic simplification of and .
p1 as .
Here are some design choices.
- Positive numbers are returned as real numbers, not as . E.g.
- If then this is not displayed. E.g.
If question level simplification is on, then the value will probably get re-simplified to Cartesian form.