Storing three scores for each of your twenty students required the use of 60 variables, out of an available 150. We're running out of room! You can save space by defining “segmented” variables which make it easy to keep several numbers in each student variable. For example, you can write a definition of the form:
This identifies “score” as an array which starts at v31 and consists of segments holding positive integers (whole numbers) smaller than 27 (which is 128). It turns out that each student variable will hold 8 such segments, so “score(8)” is the last segment in v31, while “score(9)” is the first segment in v32. Since “score(60)” is the fourth segment in v38, we need only eight variables to hold all sixty scores. You can use “score(expr)” in calculations. The expression “expr” will be rounded to the nearest integer and the appropriate segment referenced. As a simple example:
If we define a segmented one-dimensional array “score”, we can define a two-dimensional array as before:
In this case you use “scores” rather than “scores(exprl,expr2) in calculations. NOTE: At the present writing, the commands -zero- and -transfrcannot be used with segmented variables because these commands refer to entire variables. You could, however, zero all of the scores by saying “zero v31,8” which sets v31 through v38 to zero, which has the effect of zeroing all the segments contained in those eight variables. You can make such manipulations more readable by defining your segmented array this way:
It is possible to store integers (whole numbers) that can be negative as well as positive:
The addition of the word “signed” (or the abbreviation “s”) permits you to hold in “temp(i)” any integer from -63 to +63. The range 27 (128) has been cut essentially in half to accommodate negative as well as positive values. The following table summarizes the unsigned and signed ranges of integers permissible for various segment size specifications up to 30 (sizes up to 59 are allowed, though beyond 30 there is only one segment per variable).
Segment Size | Unsigned Range | Signed Range | #Segs/var | |
---|---|---|---|---|
n | 2n | |||
01 | 2 | 0 to 1 | -0 to +0 | 60 |
02 | 4 | 0 to 3 | -1 to +1 | 30 |
03 | 8 | 0 to 7 | -3 to +3 | 20 |
04 | 16 | 0 to 15 | -7 to +7 | 15 |
05 | 32 | 0 to 31 | -15 to +15 | 12 |
06 | 64 | 0 to 63 | -31 to +31 | 10 |
07 | 128 | 0 to 127 | -63 to +63 | 8 |
08 | 256 | 0 to 255 | -127 to +127 | 7 |
09 | 512 | 0 to 511 | -255 to +255 | 6 |
10 | 1,024 | 0 to 1,023 | -511 to +511 | 6 |
11 | 2,048 | 0 to 2,047 | -1,023 to +1,023 | 5 |
12 | 4,096 | 0 to 4,095 | -2,047 to +2,047 | 5 |
13 | 8,192 | 0 to 8,191 | -4,095 to +4,095 | 4 |
14 | 16,384 | 0 to 16,383 | -8,191 to +8,191 | 4 |
15 | 32,768 | 0 to 32,767 | -16,383 to +16,383 | 4 |
16 | 65,536 | 0 to 65,535 | -32,767 to +32,767 | 3 |
17 | 131,072 | 0 to 131,071 | -65,535 to +65,535 | 3 |
18 | 262,144 | 0 to 262,143 | -131,071 to +131,071 | 3 |
19 | 524,288 | 0 to 524,287 | -262,143 to +262,143 | 3 |
20 | 1,048,576 | 0 to 1,048,575 | -524,287 to +524,287 | 3 |
21 | 2,097,152 | 0 to 2,097,151 | -1,048,575 to +1,048,575 | 2 |
22 | 4,194,304 | 0 to 4,194,303 | -2,097,151 to +2,097,151 | 2 |
23 | 8,388,608 | 0 to 8,388,607 | -4,194,303 to +4,194,303 | 2 |
24 | 16,777,216 | 0 to 16,777,215 | -8,388,607 to +8,388,607 | 2 |
25 | 33,554,432 | 0 to 33,554,431 | -16,777,215 to +16,777,215 | 2 |
26 | 67,108,864 | 0 to 67,108,863 | -33,554,431 to +33,554,431 | 2 |
27 | 134,217,728 | 0 to 134,217,727 | -67,108,863 to +67,108,863 | 2 |
28 | 268,435,456 | 0 to 268,435,455 | -134,217,727 to +134,217,727 | 2 |
29 | 536,870,912 | 0 to 536,870,911 | -268,435,455 to +268,435,455 | 2 |
30 | 1,073,741,824 | 0 to 1,073,741,823 | -536,870,911 to +536,870,911 | 2 |
As an example of the use of this table, suppose you are dealing with integers in the range from -1200 to +1800. You would need a segment size of 12 (signed), which gives a range from -2047 to +2047. There would be 5 segments in each variable. Your -define- might look like:
It is not necessary to understand the rationale behind this table in order to be able to use segments effectively. Explanations of the underlying “binary” or “base 2” number system and the associated concept of a “bit” are discussed later in an optional section of this chapter.
Segments are frequently used to set “flags” or markers in a lesson. For example, you might like to keep track of the topics the student has completed or which questions in a drill have been attempted. A segment size of just one is sufficient for such things, with the segment first initialized to zero, then set to one when the topic or question has been covered. The definition might look like this:
In the first unit, (not the “initial entry unit”) use the statement “zero flags” to clear all sixty segments in v2. If you use up to 120 markers you would use “zero flags,2” to clear two variables, each containing 60 segments. When the student completes the fourth topic you use “calc flag(4)⇐1” to set the fourth flag. You can retrieve this information at any time to display to the student which topics he or she has completed. Note that the -restart- command can be used to restart the student somewhere after the first unit (where the flags would otherwise be cleared), so that you can remind the student of which sections he or she completed during previous sessions.
Although only whole numbers can he kept in segments, it is possible to use the space-saving features of segments even when dealing with fractional numbers. Suppose you have prices of items which (in dollars and cents) involve fractions such as $37.65 (37 dollars plus 65 hundredths of a dollar). Assume that $50 is the highest price for an item. Simply express the prices in cents, with the top price then being 5000 cents. Using the table, we see that a segment size of 13 will hold positive integers up to 8191, so we say
A sequence using these definitions might look like:
The final -show- will put “28.37” on the screen, even though between the “put” and “get”, the number was the integer “2837”. Notice the unusual “calc put(16)” which has an assignment (⇐) implicit in the definition of “put”. Also notice that the variable “price” is changed as a side-effect of “get”. If this is not desired, we could define “get(i)=cents(i)/100”.
As another example of the use of segments with fractional numbers, suppose you have automobile trip mileages up to 1000 miles which you want to store to the nearest tenth-mile (such as 243.8 miles). In this ease you must multiply by 10 when storing into a segment and divide by 10 when retrieving the information. You would use a segment size of 14, since your biggest number is 10000. It should be pointed out that rounding to the nearest integer occurs when storing a non-integer value into a segment:
So, by going into and out of the segment, the “539.47” has turned into “539.5”.
Aside from the restriction to integers, calculations with segmented variables have one further disadvantage: they are much slower than calculations with whole variables. This is due to the extra manipulations the computer must perform in computing which variable contains the Nth segment, and extracting or inserting the appropriate segment. Segments save space at the expense of time. In many cases this does not matter, but you should avoid doing a lot of segment calculations in a heavily-computational repetitive loop, such as an iterative -do- which is done ten thousand times. (There are other kinds of segments, “vertical” segments, which are handled much faster but these have quite different space requirements than regular segmented variables.)