calc: Modes Tutorial
3.1.4 Mode-Setting Commands
---------------------------
Calc has many types of “modes” that affect the way it interprets your
commands or the way it displays data. We have already seen one mode,
namely Algebraic mode. There are many others, too; we’ll try some of
the most common ones here.
Perhaps the most fundamental mode in Calc is the current “precision”.
Notice the ‘12’ on the Calc window’s mode line:
--%*-Calc: 12 Deg (Calculator)----All------
Most of the symbols there are Emacs things you don’t need to worry
about, but the ‘12’ and the ‘Deg’ are mode indicators. The ‘12’ means
that calculations should always be carried to 12 significant figures.
That is why, when we type ‘1 <RET> 7 /’, we get ‘0.142857142857’ with
exactly 12 digits, not counting leading and trailing zeros.
You can set the precision to anything you like by pressing ‘p’, then
entering a suitable number. Try pressing ‘p 30 <RET>’, then doing ‘1
<RET> 7 /’ again:
1: 0.142857142857
2: 0.142857142857142857142857142857
.
Although the precision can be set arbitrarily high, Calc always has
to have _some_ value for the current precision. After all, the true
value ‘1/7’ is an infinitely repeating decimal; Calc has to stop
somewhere.
Of course, calculations are slower the more digits you request.
Press ‘p 12’ now to set the precision back down to the default.
Calculations always use the current precision. For example, even
though we have a 30-digit value for ‘1/7’ on the stack, if we use it in
a calculation in 12-digit mode it will be rounded down to 12 digits
before it is used. Try it; press <RET> to duplicate the number, then
‘1 +’. Notice that the <RET> key didn’t round the number, because it
doesn’t do any calculation. But the instant we pressed ‘+’, the number
was rounded down.
1: 0.142857142857
2: 0.142857142857142857142857142857
3: 1.14285714286
.
In fact, since we added a digit on the left, we had to lose one digit on
the right from even the 12-digit value of ‘1/7’.
How did we get more than 12 digits when we computed ‘2^3^4’? The
answer is that Calc makes a distinction between “integers” and
“floating-point” numbers, or “floats”. An integer is a number that does
not contain a decimal point. There is no such thing as an “infinitely
repeating fraction integer,” so Calc doesn’t have to limit itself. If
you asked for ‘2^10000’ (don’t try this!), you would have to wait a long
time but you would eventually get an exact answer. If you ask for
‘2.^10000’, you will quickly get an answer which is correct only to 12
places. The decimal point tells Calc that it should use floating-point
arithmetic to get the answer, not exact integer arithmetic.
You can use the ‘F’ (‘calc-floor’) command to convert a
floating-point value to an integer, and ‘c f’ (‘calc-float’) to convert
an integer to floating-point form.
Let’s try entering that last calculation:
1: 2. 2: 2. 1: 1.99506311689e3010
. 1: 10000 .
.
2.0 <RET> 10000 <RET> ^
Notice the letter ‘e’ in there. It represents “times ten to the power
of,” and is used by Calc automatically whenever writing the number out
fully would introduce more extra zeros than you probably want to see.
You can enter numbers in this notation, too.
1: 2. 2: 2. 1: 1.99506311678e3010
. 1: 10000. .
.
2.0 <RET> 1e4 <RET> ^
Hey, the answer is different! Look closely at the middle columns of the
two examples. In the first, the stack contained the exact integer
‘10000’, but in the second it contained a floating-point value with a
decimal point. When you raise a number to an integer power, Calc uses
repeated squaring and multiplication to get the answer. When you use a
floating-point power, Calc uses logarithms and exponentials. As you can
see, a slight error crept in during one of these methods. Which one
should we trust? Let’s raise the precision a bit and find out:
. 1: 2. 2: 2. 1: 1.995063116880828e3010
. 1: 10000. .
.
p 16 <RET> 2. <RET> 1e4 ^ p 12 <RET>
Presumably, it doesn’t matter whether we do this higher-precision
calculation using an integer or floating-point power, since we have
added enough “guard digits” to trust the first 12 digits no matter what.
And the verdict is... Integer powers were more accurate; in fact, the
result was only off by one unit in the last place.
Calc does many of its internal calculations to a slightly higher
precision, but it doesn’t always bump the precision up enough. In each
case, Calc added about two digits of precision during its calculation
and then rounded back down to 12 digits afterward. In one case, it was
enough; in the other, it wasn’t. If you really need X digits of
precision, it never hurts to do the calculation with a few extra guard
digits.
What if we want guard digits but don’t want to look at them? We can
set the “float format”. Calc supports four major formats for
floating-point numbers, called “normal”, “fixed-point”, “scientific
notation”, and “engineering notation”. You get them by pressing ‘d n’,
‘d f’, ‘d s’, and ‘d e’, respectively. In each case, you can supply a
numeric prefix argument which says how many digits should be displayed.
As an example, let’s put a few numbers onto the stack and try some
different display modes. First, use ‘M-0 <DEL>’ to clear the stack,
then enter the four numbers shown here:
4: 12345 4: 12345 4: 12345 4: 12345 4: 12345
3: 12345. 3: 12300. 3: 1.2345e4 3: 1.23e4 3: 12345.000
2: 123.45 2: 123. 2: 1.2345e2 2: 1.23e2 2: 123.450
1: 12.345 1: 12.3 1: 1.2345e1 1: 1.23e1 1: 12.345
. . . . .
d n M-3 d n d s M-3 d s M-3 d f
Notice that when we typed ‘M-3 d n’, the numbers were rounded down to
three significant digits, but then when we typed ‘d s’ all five
significant figures reappeared. The float format does not affect how
numbers are stored, it only affects how they are displayed. Only the
current precision governs the actual rounding of numbers in the
Calculator’s memory.
Engineering notation, not shown here, is like scientific notation
except the exponent (the power-of-ten part) is always adjusted to be a
multiple of three (as in “kilo,” “micro,” etc.). As a result there will
be one, two, or three digits before the decimal point.
Whenever you change a display-related mode, Calc redraws everything
in the stack. This may be slow if there are many things on the stack,
so Calc allows you to type shift-‘H’ before any mode command to prevent
it from updating the stack. Anything Calc displays after the
mode-changing command will appear in the new format.
4: 12345 4: 12345 4: 12345 4: 12345 4: 12345
3: 12345.000 3: 12345.000 3: 12345.000 3: 1.2345e4 3: 12345.
2: 123.450 2: 123.450 2: 1.2345e1 2: 1.2345e1 2: 123.45
1: 12.345 1: 1.2345e1 1: 1.2345e2 1: 1.2345e2 1: 12.345
. . . . .
H d s <DEL> U <TAB> d <SPC> d n
Here the ‘H d s’ command changes to scientific notation but without
updating the screen. Deleting the top stack entry and undoing it back
causes it to show up in the new format; swapping the top two stack
entries reformats both entries. The ‘d <SPC>’ command refreshes the
whole stack. The ‘d n’ command changes back to the normal float format;
since it doesn’t have an ‘H’ prefix, it also updates all the stack
entries to be in ‘d n’ format.
Notice that the integer ‘12345’ was not affected by any of the float
formats. Integers are integers, and are always displayed exactly.
Large integers have their own problems. Let’s look back at the
result of ‘2^3^4’.
2417851639229258349412352
Quick—how many digits does this have? Try typing ‘d g’:
2,417,851,639,229,258,349,412,352
Now how many digits does this have? It’s much easier to tell! We can
actually group digits into clumps of any size. Some people prefer ‘M-5
d g’:
24178,51639,22925,83494,12352
Let’s see what happens to floating-point numbers when they are
grouped. First, type ‘p 25 <RET>’ to make sure we have enough precision
to get ourselves into trouble. Now, type ‘1e13 /’:
24,17851,63922.9258349412352
The integer part is grouped but the fractional part isn’t. Now try ‘M--
M-5 d g’ (that’s meta-minus-sign, meta-five):
24,17851,63922.92583,49412,352
If you find it hard to tell the decimal point from the commas, try
changing the grouping character to a space with ‘d , <SPC>’:
24 17851 63922.92583 49412 352
Type ‘d , ,’ to restore the normal grouping character, then ‘d g’
again to turn grouping off. Also, press ‘p 12’ to restore the default
precision.
Press ‘U’ enough times to get the original big integer back. (Notice
that ‘U’ does not undo each mode-setting command; if you want to undo a
mode-setting command, you have to do it yourself.) Now, type ‘d r 16
<RET>’:
16#200000000000000000000
The number is now displayed in “hexadecimal”, or “base-16” form.
Suddenly it looks pretty simple; this should be no surprise, since we
got this number by computing a power of two, and 16 is a power of 2. In
fact, we can use ‘d r 2 <RET>’ to see it in actual binary form:
2#1000000000000000000000000000000000000000000000000000000 ...
We don’t have enough space here to show all the zeros! They won’t fit
on a typical screen, either, so you will have to use horizontal
scrolling to see them all. Press ‘<’ and ‘>’ to scroll the stack window
left and right by half its width. Another way to view something large
is to press ‘`’ (grave accent) to edit the top of stack in a separate
window. (Press ‘C-c C-c’ when you are done.)
You can enter non-decimal numbers using the ‘#’ symbol, too. Let’s
see what the hexadecimal number ‘5FE’ looks like in binary. Type
‘16#5FE’ (the letters can be typed in upper or lower case; they will
always appear in upper case). It will also help to turn grouping on
with ‘d g’:
2#101,1111,1110
Notice that ‘d g’ groups by fours by default if the display radix is
binary or hexadecimal, but by threes if it is decimal, octal, or any
other radix.
Now let’s see that number in decimal; type ‘d r 10’:
1,534
Numbers are not _stored_ with any particular radix attached. They’re
just numbers; they can be entered in any radix, and are always displayed
in whatever radix you’ve chosen with ‘d r’. The current radix applies
to integers, fractions, and floats.
(•) *Exercise 1.* Your friend Joe tried to enter one-third as
‘3#0.1’ in ‘d r 3’ mode with a precision of 12. He got ‘3#0.0222222...’
(with 25 2’s) in the display. When he multiplied that by three, he got
‘3#0.222222...’ instead of the expected ‘3#1’. Next, Joe entered
‘3#0.2’ and, to his great relief, saw ‘3#0.2’ on the screen. But when
he typed ‘2 /’, he got ‘3#0.10000001’ (some zeros omitted). What’s
going on here? 1 Modes Answer 1. (•)
(•) *Exercise 2.* Scientific notation works in non-decimal modes in
the natural way (the exponent is a power of the radix instead of a power
of ten, although the exponent itself is always written in decimal).
Thus ‘8#1.23e3 = 8#1230.0’. Suppose we have the hexadecimal number
‘f.e8f’ times 16 to the 15th power: We write ‘16#f.e8fe15’. What is
wrong with this picture? What could we write instead that would work
better? 2 Modes Answer 2. (•)
The ‘m’ prefix key has another set of modes, relating to the way Calc
interprets your inputs and does computations. Whereas ‘d’-prefix modes
generally affect the way things look, ‘m’-prefix modes affect the way
they are actually computed.
The most popular ‘m’-prefix mode is the “angular mode”. Notice the
‘Deg’ indicator in the mode line. This means that if you use a command
that interprets a number as an angle, it will assume the angle is
measured in degrees. For example,
1: 45 1: 0.707106781187 1: 0.500000000001 1: 0.5
. . . .
45 S 2 ^ c 1
The shift-‘S’ command computes the sine of an angle. The sine of 45
degrees is ‘sqrt(2)/2’; squaring this yields ‘2/4 = 0.5’. However,
there has been a slight roundoff error because the representation of
‘sqrt(2)/2’ wasn’t exact. The ‘c 1’ command is a handy way to clean up
numbers in this case; it temporarily reduces the precision by one digit
while it re-rounds the number on the top of the stack.
(•) *Exercise 3.* Your friend Joe computed the sine of 45 degrees as
shown above, then, hoping to avoid an inexact result, he increased the
precision to 16 digits before squaring. What happened? 3 Modes
Answer 3. (•)
To do this calculation in radians, we would type ‘m r’ first. (The
indicator changes to ‘Rad’.) 45 degrees corresponds to ‘pi/4’ radians.
To get ‘pi’, press the ‘P’ key. (Once again, this is a shifted capital
‘P’. Remember, unshifted ‘p’ sets the precision.)
1: 3.14159265359 1: 0.785398163398 1: 0.707106781187
. . .
P 4 / m r S
Likewise, inverse trigonometric functions generate results in either
radians or degrees, depending on the current angular mode.
1: 0.707106781187 1: 0.785398163398 1: 45.
. . .
.5 Q m r I S m d U I S
Here we compute the Inverse Sine of ‘sqrt(0.5)’, first in radians, then
in degrees.
Use ‘c d’ and ‘c r’ to convert a number from radians to degrees and
vice-versa.
1: 45 1: 0.785398163397 1: 45.
. . .
45 c r c d
Another interesting mode is “Fraction mode”. Normally, dividing two
integers produces a floating-point result if the quotient can’t be
expressed as an exact integer. Fraction mode causes integer division to
produce a fraction, i.e., a rational number, instead.
2: 12 1: 1.33333333333 1: 4:3
1: 9 . .
.
12 <RET> 9 / m f U / m f
In the first case, we get an approximate floating-point result. In the
second case, we get an exact fractional result (four-thirds).
You can enter a fraction at any time using ‘:’ notation. (Calc uses
‘:’ instead of ‘/’ as the fraction separator because ‘/’ is already used
to divide the top two stack elements.) Calculations involving fractions
will always produce exact fractional results; Fraction mode only says
what to do when dividing two integers.
(•) *Exercise 4.* If fractional arithmetic is exact, why would you
ever use floating-point numbers instead? 4 Modes Answer 4. (•)
Typing ‘m f’ doesn’t change any existing values in the stack. In the
above example, we had to Undo the division and do it over again when we
changed to Fraction mode. But if you use the evaluates-to operator you
can get commands like ‘m f’ to recompute for you.
1: 12 / 9 => 1.33333333333 1: 12 / 9 => 1.333 1: 12 / 9 => 4:3
. . .
' 12/9 => <RET> p 4 <RET> m f
In this example, the righthand side of the ‘=>’ operator on the stack is
recomputed when we change the precision, then again when we change to
Fraction mode. All ‘=>’ expressions on the stack are recomputed every
time you change any mode that might affect their values.