TI-Basic Developer

The TI-Basic Information Repository


The Home Screen and Its Commands

The TI-83/+/SE home screen is composed of eight rows (1 to 8 from top to bottom) by sixteen columns (1 to 16 from left to right); it is like a grid. The home screen uses the large, easy to see, 5 by 7 font. Because each character takes up the same 5 by 7 space, regardless of what its actual size is, the text cannot be moved around to get pixel perfect precision.
The table below shows the coordinates used for the Output( command (see below). Enter these coordinates in the Output( command as shown, only without the parentheses. There is different coordinates for a TI-84+C SE.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8) (1,9) (1,10) (1,11) (1,12) (1,13) (1,14) (1,15) (1,16)
2 (2,1) (2,2) (2,3) (2,4) (2,5) (2,6) (2,7) (2,8) (2,9) (2,10) (2,11) (2,12) (2,13) (2,14) (2,15) (2,16)
3 (3,1) (3,2) (3,3) (3,4) (3,5) (3,6) (3,7) (3,8) (3,9) (3,10) (3,11) (3,12) (3,13) (3,14) (3,15) (3,16)
4 (4,1) (4,2) (4,3) (4,4) (4,5) (4,6) (4,7) (4,8) (4,9) (4,10) (4,11) (4,12) (4,13) (4,14) (4,15) (4,16)
5 (5,1) (5,2) (5,3) (5,4) (5,5) (5,6) (5,7) (5,8) (5,9) (5,10) (5,11) (5,12) (5,13) (5,14) (5,15) (5,16)
6 (6,1) (6,2) (6,3) (6,4) (6,5) (6,6) (6,7) (6,8) (6,9) (6,10) (6,11) (6,12) (6,13) (6,14) (6,15) (6,16)
7 (7,1) (7,2) (7,3) (7,4) (7,5) (7,6) (7,7) (7,8) (7,9) (7,10) (7,11) (7,12) (7,13) (7,14) (7,15) (7,16)
8 (8,1) (8,2) (8,3) (8,4) (8,5) (8,6) (8,7) (8,8) (8,9) (8,10) (8,11) (8,12) (8,13) (8,14) (8,15) (8,16)

The home screen does not have access to any of the drawing commands that are available on the graph screen (such as the points, pixels, lines, or circles). This leaves you with just using the text to imitate graphics, which unfortunately does not look very good. Using the home screen is faster than using the graph screen, though.

There are five main home screen commands:

  • ClrHome — Clears the home screen of any text or numbers. It should be used at the beginning of a program and at the end to make sure the user has a clear screen afterwards.
  • Disp — Displays one or more arguments of text or values on a new line on the home screen and scrolls down if necessary. Disp should be used instead of Output( in most cases.
  • Output( — Displays text or a value at a specified row and column location on the home screen. It also wraps the text or value around the screen if needed.
  • Pause — Pauses the program and displays the home screen until the user presses ENTER. It also can display text or a value with scrolling available.
  • Menu( — Displays a generic menu on the home screen, with up to seven options for the user to select from. It utilizes branching to make the menu.

You should commit yourself to learning how to use these commands and then actually start using them in your programs. They are rather basic, but still quite powerful. Once you have them down, move on to the graph screen commands.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/homescreen


The Graphscreen and Its Commands

The TI-83/+/SE graphscreen is 64 rows, by 96 columns, the coordinates for the pixels being 0 to 62 a total of 63 and 0 to 93 a total of 94. So amount of editable X and Y pixels are 95 and 63. With the coordinates 0,0 actually being the very top left pixel. The graphscreen uses the small (3 by 5) font, which allows you to display more text; and the large (5 by 7) font, which allows you to make the graphscreen look like the homescreen. On the color calculators, the available screen is 165rows by 265 columns, starting at 0. Graphics can also be displayed on the graphscreen, in the form of points, pixels, lines, or circles, as well as shading an area of the graphscreen. These graphics can be displayed with the text, and they can be saved to pictures for later use.

The graphscreen does not have access to some of the commands that are available on the homescreen (such as the user input). In addition, some of the graphscreen commands have their coordinates reversed, so the row comes before the column. These commands also take longer to draw.

Setting up the Graphscreen

Note: it is good practice to save the current settings at the beginning of the program with StoGDB, and recall it later with RclGDB. The syntax for those commands is illustrated below.

Before using the graphscreen, you first need to set it up appropriately. When displaying text or drawing graphics, you want to make sure that they are displayed how you want them to be displayed. This is achieved by clearing the graphscreen, adjusting the window dimensions, and turning off the graph formats.

Clearing the Graphscreen

The ClrDraw command is the graphscreen equivalent to ClrHome. ClrDraw is usually used before you display text or draw anything on the graphscreen, to ensure that it won't be interrupted by anything that was previously displayed on the graphscreen.

Format
:ClrDraw

You also want to make sure to clear the graphscreen when exiting programs. This ensures that the next program that the user runs won't have to deal with whatever text or graphics your program left behind. It also helps the user, because they won't have to manually clear the graphscreen.

To use the ClrDraw command, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM. Then press ENTER on ClrDraw. Now the command has been put into your program.

Adjusting the Window Dimensions

After clearing the graphscreen, you will want to set the window dimensions to the desired size. There are four window variables that control the window dimensions: Xmin, Xmax, Ymin, and Ymax. When storing values in these variables, you have to remember that the max variables always have to be larger then the min variables, otherwise you will get an error.

The Xmin variable sets the minimum value that the X coordinate can have. The Xmax variable sets the maximum value that the X coordinate can have. The Ymin variable sets the minimum value that the Y coordinate can have. The Ymax variable sets the maximum value that the Y coordinate can have. You can use these variables like regular variables.

Format
:#→Xmin:#→Xmax
:#→Ymin:#→Ymax

Although the graphscreen is 96 pixels wide by 64 pixels tall on the monochrome calculators, and 320 pixels wide by 240 pixels tall on the color calculators, the bottom row is unusable for monochrome TI-Basic programs and the far right column is reserved for the monochrome pause indicator. On the color calculators, the screen is taken up with a border, and the info bar on the top of the screen. So, most monochrome programmers set the window dimensions to 0 for Xmin and Ymin, 94 for Xmax, and 62 for Ymax. This sets the X range from -1 to 94 totaling 95 columns and the Y range from -1 to 62 totaling 63. On the color calculators, most programs set the screen to ZStandard, then ZSquare, making the screen 20 spaces on the Y axis, and just over 32 on the X.

Format
:0→Xmin:94→Xmax
:0→Ymin:62→Ymax

In a simpler notion, to make everything positive from the bottom left corner you would use the following code.

Format
:1→Xmin:95→Xmax
:1→Ymin:63→Ymax

Others set 0 for Xmin and Ymax, 94 for Xmax and -62 for Ymin. This allows them to use the same coordinates for pixel and point commands, as pixel rows on the screen are counted starting from the top. So the top pixel row is 0 and the bottom row is 62, while the point top row is 0 and bottom row is -62.

In addition to those four window variables, there are two other window variables that you can use to set the window dimensions. ΔX is the difference between Xmin and Xmax divided by the graphscreen width and ΔY is the difference between Ymin and Ymax divided by the graphscreen height. When you set Xmin and Ymin to 0, you just need to set ΔX and ΔY to 1 to make Xmax 94 and Ymin 62.

:0→Xmin:94→Xmax
:0→Ymin:62→Ymax
Replace with ΔX and ΔY
:0→Xmin:1→ΔX
:0→Ymin:1→ΔY

To use the window variables, you should first be in the Program editor for your program. In the Program editor, press VARS and 1, then scroll down to whichever variable you want to use and press ENTER. Now the variable has been put into your program. You then have to type what number you want to set the window variable to.

In addition to setting the window variables individually, there are also a couple commands that can set them all at the same time. Although these commands are only useful in a couple situations, they are a lot easier (and smaller) to use.

The ZStandard command sets the window dimensions to their default settings (which is -10 for Xmin and Ymin, and 10 for Xmax and Ymax). The ZSquare command sets the window dimensions so that they make the screen square. This is important when drawing circles because it makes the circles look like circles (instead of ellipses).

Format
:ZStandard
:ZSquare

To use the ZStandard or ZSquare command, you should first be in the Program editor for your program. In the Program editor, press the ZOOM key. Then scroll down to whichever command you want to use and press ENTER. Now the command has been put into your program.

Turning off the Graph Formats

After adjusting the window dimensions, you will want to turn off the graph formats. The graph formats include the grids, plots, axes, and functions. These can be turned off and turned on, depending on what is desired.

The GridOff command turns the grid off and the GridOn command turns the grid on. The PlotsOff command turns the plots off and the PlotsOn command turns the plots on. The AxesOff command turns the axes off and the AxesOn command turns the axes on. The FnOff command turns all of the functions off and the FnOn command turns all of the functions on.

Format
:GridOff/On
:PlotsOff/On
:AxesOff/On
:FnOff/On

The plots and functions commands can also be used to just deal with one or two plots or functions, instead of all of them. You just put the plots or functions and their numbers after the command, separating each one with a comma.

Format
:PlotsOff/On function#[,function#,...]
:FnOff/On function#[,function#,...]

To use the graph formats, you should first be in the Program editor for your program. In the Program editor, press 2nd and ZOOM. Then scroll down to GridOff/On or AxesOff/On and press ENTER. To use the PlotsOff/On or FnOff/on commands, you need to press 2nd and 0 for the Catalog menu. Then scroll down to the command or press the first letter of the command and press ENTER. Now the command has been put into your program.

Graph Databases (GDB)

There are 10 graph database (GDB) variables (GDB0 through GDB9) that store the window and graph format settings, so they can later be used to recreate the graphscreen; GDBs do not contain graphics or stat plot definitions. If a program utilizes the graphscreen, it should restore the graphscreen settings with a GDB when the program finishes executing.

The StoreGDB command saves the graph settings in a GDB. It is best used at the beginning of a program. The RecallGDB command restores the graph settings that are stored in a GDB. It is best used after a program is finished executing. You should remember to delete the GDB after recalling it.

Format
:StoreGDB #
:RecallGDB #

To use the GDB commands, you should first be in the Program editor for your program. In the Program editor, press 2nd DRAW and > > twice. Then scroll down to StoreGDB or RecallGDB and press ENTER. Finally, press the number of the GDB you want to use.

Putting all of these commands together, here is a typical way to set up the graphscreen at the beginning of a program:

PROGRAM:GRAPHSET
:StoreGDB 1
:ClrDraw
:GridOff
:PlotsOff
:AxesOff
:FnOff
:0→Xmin:1→ΔX
:0→Ymin:1→ΔY

Graphing Functions on the Graphscreen

Graphing functions is primarily used in math programs. There are three commands that are used for graphing functions: DrawF, DrawInv, and Tangent. The commands do not change the function variables, and their graphs (and tangent line) are erased when any command changes the graphscreen.

The DrawF command graphs an expression. The DrawInv command graphs the inverse of an expression by plotting X values on the y-axis and Y values on the x-axis (as if the X and Y values are switched). The Tangent command draws a line tangent to the expression, with the line touching the expression at the X value. Use the Input or Pause command to view the graph (or tangent line).

Format
:DrawF expression
:DrawInv expression
:Tangent(expression,value)

The expression can either be a function variable (Y0 through Y9) or a function in terms of X (such as 3X+4). While you create a function variable by storing an expression (enclosed in quotes) to it, the function in terms of X is just the expression itself (which allows you to bypass the function variable). The expression can consist of numbers, variables, and math functions.

Format
:"expression"→Y#
:expression

After the function variable is created, it is stored in the Y= editor and selected to be graphed. If you already have an expression stored in a function variable, you can combine function variables with other expressions to create new expressions. You cannot use a list in the expression to draw several graphs at one time.

When graphing functions, you have to adjust the graph formats and window dimensions to ensure the functions display correctly on the screen. Although you can have successive graphs (graphs displayed on top of each other), this is sometimes unwanted because it interrupts the graphscreen while you're graphing your functions. You can get rid of this problem by using the FnOff command.

To use the graph commands, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM, then scroll down to whichever command you want and press ENTER. Now the command has been put into your program. You then have to type the expression you want to graph. The function variables can be found by pressing VARS, pressing > once to get to the Y-Vars menu, and then scrolling down to Functions.

Displaying Text on the Graphscreen

The Text command displays text, numbers, variables, or expressions wherever you want on the graphscreen. Because the Text command utilizes the small font (available only on the graphscreen), more text can be displayed on the screen. The Text command overwrites any existing text on the screen, and it is also not affected by the graphscreen window settings.

When you use the Text command, you need to specify the starting coordinates of what you want to display. You first specify the row (0 to 57 from top to bottom) and then the column (0 to 91 from left to right). Although the graphscreen is actually 94 rows by 62 columns, you will get an error if you try to display text on a higher row or column.

The reason is that the graphscreen text is five pixels tall and a variable width. While numbers, uppercase letters, and most lowercase letters are three pixels wide, some lowercase letters (such as w and m) are five pixels wide, and spaces are one pixel wide. There is an automatic space (one pixel wide) inserted between text. So, you need to factor in the height and width of the characters when positioning them on the screen.

Format
:Text(row,col,argument)

A good way to find where exactly you want to place the text or other drawing is to use a blank Input command. This gives you a cursor to find where to put it. Just remember that the coordinates at the bottom of the screen are not what you put into the Text( command.

Format
:Input

The Text command can display multiple arguments of both text and variables on the same line, at the same time. This is very useful because it eliminates the need to have to worry about spacing. If the variable changes, the Text command will adjust it on the screen accordingly. This allows you to sometimes remove multiple Text commands and just use the first one to display everything.

:Text(5,5,A
:Text(5,9,"/
:Text(5,13,B
Combine Text Commands
:Text(5,5,A,"/",B

On the TI-83+/SE calculators, the Text command can also display the large font that is available on the homescreen. Just put a negative one (-1) before the row and column arguments. When using the large font, you have to keep formatting in mind because it is very easy for the text to go off the screen. This is useful when you want to clear large portions of the graphscreen at a time.

Format
:Text(-1,row,col,argument)

If you have a string of numbers that you are displaying, you don't need to put quotes around the numbers. You may want to keep the numbers in a string, though, if they have any leading zeros. Because the numbers are no longer in a string, the leading zeros will be truncated (taken off) and not be shown.

:Text(2,2,"2345
Remove the Quotes
:Text(2,2,2345

To use the Text command, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM. Then, scroll down (all the way at the bottom) to Text and press ENTER. Now the Text command has been put into your program. You can then begin typing some text by turning on the alpha-lock with pressing 2nd and ALPHA.

Drawing & Shading on the Graphscreen

Drawing on the graphscreen is one of the main uses of the graphscreen. There are several different things that you can draw, including points, pixels, lines, and circles. Besides drawing, you can also shade in an area on the graphscreen with whatever size and look you want.

Drawing Points

The point commands are used to draw points on the graphscreen. A point is just a pixel on the screen. The point commands use the (x,y) coordinate system, which is affected by the window settings. This means you have to change the window settings accordingly when you use the point commands, otherwise the points won't show up correctly.

The Pt-On command turns on the point at the given (x,y) coordinates. The Pt-Off command turns off the point at the given (x,y) coordinates. The Pt-Change command toggles the point at the given (x,y) coordinates. If the point is on, it will be turned off and vice versa.

Format
:Pt-On(x,y)
:Pt-Off(x,y)
:Pt-Change(x,y)

The Pt-On and Pt-Off commands also have an optional mark argument that determines the shape of the point. The mark can be either one (dot), two (3x3 box), or three (3x3 cross). You don't need to specify the mark when using the first mark because it is the default. Remember to use the same mark when turning a point off as you used to turn it on.

:Pt-On(5,5,1
Remove Mark
:Pt-On(5,5

To use the point commands, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM, then press right once and scroll down to whichever command you want and press ENTER. Now the command has been put into your program. You then have to type the numbers for where you want the point to appear on the screen.

Drawing Pixels

The pixel commands are the alternative way to draw pixels on the graphscreen. Although they are easier to use because they are not affected by the window settings (which means you don't have to set the window dimensions when using them), the coordinate system is switched around so that the row comes first and then the column — it's (y,x) instead of (x,y).

The Pxl-On command turns on the pixel at the given (y,x) coordinates. The Pxl-Off command turns off the pixel at the given (y,x) coordinates. The Pxl-Change command toggles the pixel at the given (y,x) coordinates. If the pixel is on, it will be turned off and vice versa. The pixel commands are faster than their equivalent point commands, so they should generally be used instead whenever possible.

Format
:Pxl-On(y,x)
:Pxl-Off(y,x)
:Pxl-Change(y,x)

Besides these three commands that have point equivalents, there is also a Pxl-Test command. The Pxl-Test command checks whether the pixel at the given (y,x) coordinates is on or off. One is returned if the pixel is on and zero is returned if the pixel is off. You can store the result to a variable for later use, or use the command in a conditional or loop.

Format
:Pxl-Test(y,x)

To use the pixel commands, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM, then press right once and scroll down to whichever command you want and press ENTER. Now the command has been put into your program. You then have to type the numbers for where you want the pixel to appear on the screen.

Drawing Lines

The Line comand allows you to draw a line anywhere on the screen. The line can be any length that you want. When using the Line command you need to supply the coordinates of the two endpoints. The Line command draws the line from the first endpoint (x1,y1) to the second endpoint (x2,y2).

Format
:Line(x1,y1,x2,y2)

The Line command has an optional fifth argument that controls whether the line will be drawn (the argument should be one) or erased (the argument should be zero). The line is drawn by default, so it should be left off unless you want to erase it.

:Line(5,5,10,5,1
Remove Line's Fifth Argument
:Line(5,5,10,5

When you have multiple pixels in a straight line that you turn on or off, you can sometimes replace the pixel commands with one or more Line commands. In the case that the pixels are arranged at a slant or angle, you can just adjust the line coordinates accordingly. You should also use Line commands instead of pixel commands when clearing large portions of the graphscreen at a time.

:Pxl-On(5,5
:Pxl-On(5,6
:Pxl-On(5,7
Replace with Lines
:Line(5,5,5,7

There are two other line commands that are also available. They are primarily designed for when you want to quickly draw a line across the entire screen. The Horizontal command draws a horizontal line at a given row and the Vertical command draws a vertical line at a given column. The argument can either be a number or a variable.

Format
:Horizontal y
:Vertical x

To use the line commands, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM, then scroll down to whichever command you want and press ENTER. Now the command has been put into your program. You then have to type the number(s) for where you want the line to appear on the screen.

Drawing Circles

The Circle command draws a circle on the graphscreen. When using the Circle command, you must enter three numbers (separated by commas): the (x,y) coordinates of the center of the circle and the length of the radius. Because circles take a long time to draw, you should use them sparingly.

Format
:Circle(x,y,radius)

The window settings affect how the circles are drawn. With the screen height being larger than the width (the screen is a rectangle), the circles will actually look like ellipses. To make them look like circles, you need to use the ZSquare command.

To use the Circle command, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM, then scroll down to Circle and press ENTER. Now the Circle command has been put into your program. You then have to type the numbers for where you want the center of the circle to be and the length of the radius.

Shading Areas

The Shade command shades in an area on the graphscreen. For basic shading, you just need to specify a lower function and upper function. The Shade command will vertically shade in the area that is above the lower function and below the upper function across the whole length of the screen. The functions can either be a function variable (Y0 through Y9); or a function in terms of X, consisting of numbers, variables, and math functions (such as 3X+4).

Format
:Shade(lowerfunction,upperfunction)

When shading with the function variables, the window settings affect how the shading looks. You should set the window variables to ensure that the shading is done correctly. This also applies when you are shading at the same time as drawing, because some of the drawing commands are affected by the window settings.

Because you might not want to shade the whole length of the screen, the Shade command has two optional arguments that allow you to specify the left and right boundaries for shading (the boundaries themselves are also shaded). Xleft and Xright can be whatever numbers you want, as long as they are between Xmin and Xmax (the horizontal window dimensions). You can also just specify Xleft by itself if you only want to change the left boundary (you need to set Xleft to set Xright, though).

Format
:Shade(lowerfunction,upperfunction,Xleft,Xright)

The Shade command has two other optional arguments that allow you to change the look of the shading, but you need to also set the left and right boundaries to use them. The pattern can be either one (vertical), two (horizontal), three (slanted backwards), or four (slanted forwards); and the patres (the frequency of the shading) can be from one to eight pixels.

Format
:Shade(lowerfunction,upperfunction,Xleft,Xright,pattern,patres)

To use the Shade command, you should first be in the Program editor for your program. In the Program editor, press 2nd and PRGM, then scroll down to the command (or press the 7 key) and press ENTER. Now the command has been put into your program. You then have to specify the functions (and boundaries, pattern, and patres) for how you want to shade the area.

Storing the Graphscreen to a Picture

After you have spent lots of time drawing something on the graphscreen, you naturally want to keep it for future use. So, you store it to a picture variable. A picture variable holds a copy of the graphscreen at the respective time it was stored to. Although pictures are often used, it really is a personal preference.

The StorePic command saves the current graphscreen to the designated picture. After saving a picture, you can display it again with the RecallPic command. Before recalling a picture, you should first make sure that the graphscreen is clear. This ensures that the picture won't be interrupted by anything that is already on the screen. You can only use numbers with the StorePic and RecallPic commands; no variables.

Format
:StorePic #
:RecallPic #

Because each picture takes up 768 bytes, you should delete them when exiting programs. The program should only keep the picture if it is used for something important (such as a titlescreen). The user doesn't want to have their memory cluttered up with lots of variables.

To use the picture commands, you should first be in the Program editor for your program. In the Program editor, press 2nd DRAW and < once. Then scroll down to StorePic or RecallPic and press ENTER. Finally, press the number of the picture you want to use.

Advantages & Disadvantages of Pictures

The main advantage of using pictures is that the graphics show up almost instantly compared to the slow speed of drawing them. This is particularly noticeable the more detailed the graphics are and depending on what graphics (primarily circles) are being drawn. Speed is a top priority in most programs (because the user doesn't want to wait), so pictures are usually used.

The main disadvantage of using pictures is that there are only ten pictures (from Pic0 to Pic9). With every program sharing the pictures, there can be conflict when two programs use the same picture (the picture will usually be overwritten by the other program).

Another disadvantage of using pictures is that it is another file that the user needs in order to use your program. If you give someone your program, you will have to also give them your pictures. Your program won't work properly anymore if somebody deletes your pictures or forgets to include them with your program. Although this is mostly out of your hands, users will think your program is at fault.

Pictures have a weird behavior, that can be a curse or blessing. When recalled, they only turn on pixels — not turn them off. Try recalling one picture, then recalling a different picture. You'll notice they overlap. This has an application anytime that you are displaying something (sprite) on top of a background. Draw the sprite on the screen, and use a pic for the background.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/graphscreen


Math Functions

Calculators are built with one primary purpose: math. Programming, game playing, and everything else is secondary. Thus, you will find a number of powerful math commands. Although it may seem that they are of no use to a programmer, programs sometimes need math functions, and many math functions can be used in clever ways. In this guide we'll group the commands into the following general groups:

Number Operations

These commands deal with different ways you can manipulate the integer and fraction parts of a number, and are mostly found in the MATH-NUM menu.

Probability and Combinatorics

These commands are generally found in the MATH-PRB menu (except for randM(, which is in the MATRIX-MATH menu). They include commands for generating random numbers, and commands that are useful for solving problems in combinatorics and probability theory.

Calculus

Although the TI-83 series calculators don't, by themselves, have the capability for symbolic calculations, these commands (found in the main MATH menu) can provide numerical approximations for some commonly computed quantities in calculus.

  • fMin(, fMax( — numerical function optimization in one variable.
  • nDeriv(, fnInt( — derivatives and integrals.
  • solve( — numerical solution of an equation in one variable.

Trigonometry

These commands allow you to manipulate angles, and are generally affected by Radian mode and Degree mode (so you should check those pages out). Some of these commands live in the 2nd ANGLE menu, some are on the keyboard, and some can only be found in the 2nd CATALOG menu:

Complex Number Operations

These commands are used for dealing with complex numbers, and are found in the MATH-CPX menu. Many other math commands work on complex numbers too, and complex numbers are fairly strongly connected to trigonometry.

Operators

These commands are found on the keyboard and in the 2nd TEST menu, and deal with basic mathematical and logical commands.

Powers, Inverses, Exponentials, and Logarithms

These commands are found all over the place, many on the keyboard itself, and deal with raising some value to a power, or raising a number to some value, or the inverses of those operations.

Miscellaneous

These commands have nothing to do with each other, but don't really belong to other categories either.

  • π, e — famous (and occasionally, even useful) math constants.
  • min(, max( — returns the smaller number(s) or the larger number(s).
  • lcm(, gcd( — returns the least common multiple or the greatest common denominator of two numbers.

Comments

Note that the statistics commands are not included here. That is because statistics is not math. There is also the finance commands and variables, which are another topic unto themselves.

In addition, all of the above commands, except for the calculus and random number generating commands, can be applied to lists as well. For single-argument commands, this just means that the command is applied to each element of the list separately.

For multiple-argument commands, there are two ways to do it: with a number and a list (then, the command is applied with that number to each element of a list), and with two lists (then, it's done pairwise, and the lists must be the same size, otherwise the calculator will throw a ERR:DIM MISMATCH error).

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/math


Variable Types

Variables are used extensively in programming, as most programs use variables in one form or another. They are used to keep track of numbers or text or stats; there are many uses for variables. Put simply, programming wouldn't be programming without variables. Imagine variables being little boxes which you can store almost anything in.

A variable is a reference to the information that it holds. Variables allow you to store the information, so that you can later use it for whatever purpose is desired. The thing to remember, though, is that programs all share the variables.

There are several different kinds of variables available on the calculator, but the four main variables that you will be using are number variables, lists, matrices, and strings. Number variables are used for storing a single number. Lists are used for storing a collection of numbers. Matrices are used for storing numbers in a two-dimensional format. And, strings are used for storing text.

Storing & Deleting Variables

Variables have values stored in them so that the values can be recalled for later use. When storing an expression containing a variable into another variable, the value of the variable at that time is used. The store (→) command is used for storing variables, and it is accessed by pressing the [STO►] key. When storing a value in a variable, you have the value on the left side of the store command and the variable that it will be stored to on the right side.

Format
:value→variable

When you are done using variables, you should delete them with the DelVar command to save space. The DelVar command deletes the contents of a variable from memory. If the DelVar command is used with a real variable, the variable is not only deleted from memory but automatically set to zero the next time it is used. DelVar does not work on specific elements of a list or matrix. In fact, it will actually return an error.

Format
:DelVar variable

Numeric variables

Numeric variables are used for storing numbers. There are 27 numeric variables (from A to Z and θ) that can be easily accessed, and more that the calculator uses for its specific purposes.

Most numeric variables can either be real or complex (the latter involve i, the square root of -1, and are important to advanced algebra). In either case, up to 14 digits of a number can be stored, although only the first 10 will be displayed and used for comparison.

To access a real variable, press ALPHA and then the key corresponding to whatever letter you want your variable to be. You can initialize a real variable by storing a number, another variable, or an expression into the variable using the STO key (or, just using it almost anywhere will initialize it to 0).

List Variables

Lists are used to hold multiple numbers at once, in a specific order. There are six "default" lists named L1 through L6, but an important feature of lists is that they can be given names, so that there are millions of possible lists. Lists are important for programmers for many purposes - saving data after a program finishes running, and storing a level of a game are only two of them.

(for more information, see Lists and Their Commands)

Matrix Variables

Matrices are two-dimensional lists (row by column). Equivalent to lists, they are used when the data needs more structure. Matrices are often used for storing a level or a map of the screen. There are only ten matrices available (from [A] to [J]).

(for more information, see Matrices and Their Commands)

String Variables

Strings are used for storing a sequence of characters, that is, text. A common use for strings is to manipulate text to be displayed in a program, but they have many different purposes: highscores, level and map data, and whatever else is desired. Although there are only ten built-in string variables (Str0 through Str9) available to use, strings can hold many different kinds of characters, including letters (both uppercase and lowercase), numbers, functions, and even other commands. The amount of free RAM is the only limit on the number of characters in a string.

(for more information, see Strings and Their Commands)

Picture Variables and GDBs

Picture variables and GDBs (short for Graph DataBase) are used to save two different elements of the current graph display. A picture variable is used to store the exact appearance of the graph screen. A GDB is used to store system variables relevant to the graph screen - equations, window settings, and the like. 10 built-in variables of each type exist: Pic0 through Pic9 for pictures and GDB0 through GDB9 for GDBs.

(for more information, see Pictures and GDBs)

System Variables

System variables are, for the purposes of this guide, variables that certain commands will use or modify without asking (i.e. without supplying them in the command's arguments). This is a somewhat ill-defined category, and in fact the system variables we'll discuss are of a somewhat miscellaneous nature. They include equation and plot variables, window and table parameters, statistical variables, and finance variables.

(for more information, see System Variables)

Converting Between Variable Types

Between lists and matrices

The List►matr( and Matr►list( commands are used to convert between a matrix and several lists. Using these commands, it should be simple to implement any kind of conversion between these two data types.

Between strings and numbers

It is very easy to convert a string version of an expression to a number, list, or matrix: the expr( command can do it — for example, expr("5") will give you the number 5, and expr("{1,2,3}") will give you the list {1 2 3}.

Going the other way, however, is slightly more complicated because there is no built-in command to do it. What you need to use instead are a few small routines: see number to string for how to convert a number to a string. To convert a list or matrix, convert each individual element instead.

Archiving and Unarchiving Variables

On the TI-83+/84+/SE calculators, you can archive and unarchive variables. What this entails is the calculator moving the variable to the archive memory or the calculator moving the variable to RAM respectively. The main advantage of archiving a variable is that it is protected from calculator crashes, which clear the calculator's RAM. At the same time, you can't access a variable that's archived; it needs to be in RAM to use it.

:Archive L1
:UnArchive Str1

There are a couple things you need to be aware of when using Archive and UnArchive. First, since the TI-83 only has RAM, archiving is not possible, and subsequently neither of these commands are available. This means that you shouldn't use either of these commands if you plan on porting a program to the TI-83. Second, archiving does not work with the majority of the system variables, including the graphing, statistical, and finance variables. You can archive the other types of variables, however, although list variables are actually more manageable using the SetUpEditor command.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/variables


Getting Input from the User

Getting user input is a basic part of almost all programs. It provides a way of changing variables or transferring control to the user. The four commands used for getting input are: Prompt/Input, getKey, and GetCalc.

User input includes getting values for variables on the calculator, getting the keys that the user pressed, and getting a variable off of or sending a variable to another calculator over a link cable.

Getting Input

You can get input in three ways: Input, Prompt, and a graph-screen method. There are certain advantages and disadvantages to each command, and there are also certain situations where each command should be used. The first two are commands on the I/O menu of the prgm button (only while editing a program). The third has no single command. It has to be done manually. Below explains the third method a bit better.

Let us focus on the first two. Prompt and Input can be used with any variable, but some of the variables have to be entered in a certain way. If the variable is a string and you are using the Prompt command, the user must put quotes ("") around the value. However, both Prompt and Input require the user must also put curly braces ({}) around lists and square brackets ([]) around matrices.

Getting Input with Prompt

The Prompt command is the simplest way of getting user input. The Prompt command asks the user to enter a value for a variable, waiting until the user enters a value and then presses ENTER. When using Prompt, the variable that is being asked for will be displayed on the screen with an equal sign and question mark (=?) after it.

:Prompt variable

Because displaying what variable the value will be stored to does not tell the user what the variable will be used for, you can put a Disp command before the Prompt command to give the user some more insight into what an appropriate value for the variable would be. The Prompt command will be displayed one line lower, though, because the Disp command automatically creates a new line.

:Disp "Text"
:Prompt X
SCREEN01.BMP

When you have a list of Prompt commands (and each one has its own variable), you can just use the first Prompt command and combine the rest of the other Prompt commands with it. You remove the Prompt commands and combine the arguments, separating each argument with a comma. The arguments can be composed of whatever combination of variables is desired.

The advantages of combining Prompt commands are that it makes scrolling through code faster, and it is more compact (i.e. smaller) and easier to write than using the individual Prompt commands. The primary disadvantage is that it is easier to accidentally erase a Prompt command with multiple arguments. So, instead of:

:Prompt A
:Prompt Str1

Combine the Prompts and get:
:Prompt A,Str1

To use the Prompt command, you should first be in the Program editor for your program. In the Program editor, press the PRGM button, then arrow over to the I/O menu. Then, scroll down to Prompt and press ENTER. Now the Prompt command has been put into your program. You then have to type what variable(s) you want to prompt the user for (separating each one with a comma).

Final note: since the real-world applications take strings (like a username or a command) quite a bit, no-one uses Prompt because it forces the user to use quotation marks. A programmer would know to use it at the =?, but the casual user won't. 99.9% of the time, you see Input, which is discussed next.

Getting Input with Input

The other way to get input is to use the Input command. The Input command asks the user to enter a value for a variable (only one variable can be input at a time), waiting for the user to enter a value and press ENTER. The Input command, by default, does not display what variable the user is being asked for, but instead just displays a question mark.

:Input variable

Because just displaying a question mark on the screen does not really tell the user what to enter for input or what the input will be used for, the Input command has an optional text message that can be either text or a string variable that will be displayed alongside the input.

Only the first sixteen characters of the text message will be shown on the screen (because of the screen dimensions), so the text message should be kept as short as possible (a good goal is twelve characters or less). Don't worry about the user not having enough room, their input does word-wrapping.

:Input "Text",variable
:Input Str#,variable

If the text message is longer than twelve characters or you want to give the user plenty of space to enter a value, you can put a Disp command before the Input command. You break the text message up and display it in parts. The Input command will be displayed one line lower, though, because the Disp command automatically creates a new line.

:Disp "Text"
:Input "Text",variable

When you are just using the text message to tell the user what the variable being stored to is, the Prompt command makes it a byte easier. And, if there is a list of Input commands following the same pattern, you can reduce them to just one Prompt command.

:Input "A",A
:Input "B",B

Replace with Prompt and get:
:Prompt A,B

The Input command can also be used another way. When you just put the Input command by itself, the graph screen will be shown and the user can move the cursor around. When the user presses ENTER, the (x,y) coordinates of the cursor will be stored to the X and Y variables, respectively.

:Input

To use the Input command, you should first be in the Program editor for your program. In the Program editor, press the PRGM button, then arrow over to the I/O menu. Then, scroll down to Input and press ENTER. Now the Input command has been put into your program. You then have to type the text message and the variable that you want to ask the user for.

Graph Screen Method

This method has no automatic command. This must be done manually and, as you can imagine, takes a lot of space. If you value speed over design, then don't bother. Otherwise, this guide will show you how to do it.

Reading Keypresses

getkey.png

The getKey command is widely used in many programs because it allows the program to directly access user input. The getKey command returns the number of the last key pressed, and resets to 0 every time it is executed.

Every key has a number assigned to it, except for ON (which is used for breaking out of programs). The numbering system consists of two parts: the row and column. The rows go from one to ten, starting at the top; and the columns go from one to six, starting from the left. You just put the row and column together to find the key's number. The only confusing parts for beginners are the arrow key numbers.

When the getKey command is used, it's value automatically resets to 0, so the next time it is used, it no longer returns the last pressed key. Because of this, the getKey command is usually stored to a variable. Storing getKey to a variable allows the program to keep track of which key was pressed, taking different actions depending on what the key was. This opens up a variety of possibilities for the programmer. For example, using getKey inside a loop allows the program to wait for a keypress and store it:

:Repeat Ans
:getKey
:End
:Ans→K

You can also put getKey in the condition of a loop, to make the loop repeat until any key or a particular key is pressed by the user. The same thing can be done with conditionals as well. This is useful if you don't want to store getKey to a variable, but you still want to have the user press a key. It's perfect for a "PRESS ANY KEY TO CONTINUE" screen.

:Repeat getKey
:End

Note that you can get a keypress at any time by directly assigning to a variable, like so:

:getKey→K
:If K=45
:Output(1,1,"Do Something")

To use the getKey command, you should first be in the Program editor for your program. In the Program editor, press the PRGM button, then arrow over to the I/O menu. Then, scroll down to getKey and press ENTER. Now the getKey command has been put into your program.

Final Notes

Once you mastered this, you've mastered half of all programming. Literally. The other half is output. That's all a program is. A program gets user input and gets results, which are usually shown to you. Good luck to the rest of your TI-Basic venture

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/userinput


Operators

Just like other programming languages, TI-Basic has the standard set of core operators built-in (math, relational, and logical), although they each have their own syntax and rules.

Math Operators

There are five math operators: +, -, *, /, and ^. Anybody who has ever done even basic math should know and recognize at least the first four operators, but for those who don't, their meaning is pretty straightforward:

+
Adds two numbers together
-
Subtracts one number from another
*
Multiplies two numbers together
/
Divides one number by another
^
Raises a number to a power

There are two similar negative symbols on the TI-83 calculators — the subtraction symbol (the - key) and the negation symbol (the (-) key). These aren't interchangeable. However, it's almost always clear from an expression which one is being used, so the - symbol will be used to represent both throughout most of this guide.

Relational Operators

There are six relational operators: =, , >, , <, and . Just like with the math operators, these operators are used in almost every math class, and thus most people should know them.

=
X=Y is true if X is equal to Y
X≠Y is true if X is not equal to Y
>
X>Y is true if X is greater than Y
X≥Y is true if X is greater than or equal to Y
<
X<Y is true if X is less than Y
X≤Y is true if X is less than or equal to Y

Because the calculator does not have a separate time for logical values (true and false), they are represented by the numbers 1 and 0. This becomes important when dealing with piecewise expressions.

Logical Operators

There are four logical operators: and, or, not(, and xor. Their interpretations are mostly intuitive when thinking about the meaning of the English word:

and
X and Y is true if both X and Y are true
or
X or Y is true if at least one of X and Y is true
xor
X xor Y is true if only one of X and Y is true
not(
not(X) is true if X is false

Again, as with the relational operators, 1 is used to for 'true', and 0 is used for 'false'. It so happens that the logical operators treat all nonzero values as though they were 1 (true), so the expression '2 and 3' will be true just as '1 and 1'.

Here is a truth table of the various values:

A B A and B A or B A xor B not(A)
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

Order of Operations

The TI-83 series of calculators has nine priority levels for evaluating expressions. All the functions on a priority level will be calculated from left to right before moving on to the next priority level. Of course, calculations within parentheses are done first. Here is a table of the priority levels:

Priority Level Functions
1 Functions that precede their argument (such as √( or sin(), except for negation
2 Functions that follow their argument (such as 2 or !)
3 ^ and ×√
3.5 Negation
4 nPr and nCr
5 Multiplication, division, and implied multiplication
6 Addition and subtraction
7 The relational operators =, , <, >, ,
8 The logic operator and
9 The logic operators or and xor
10 Conversions such as ►Frac

TI refers to the routine that determines order of operations as the Equation Operating System (EOSTM). Unfortunately, this cool name hasn't become common usage.

Test your knowledge

Here are some sample problems on logical operators, in order of complexity. For the more difficult ones, it may be best to break them up into smaller parts and work in steps.

# Question
1 0 and 1 or 1
2 0 and (1 or 1)
3 4 and -4 xor (.6 and 0)
4 not(1) xor (1 and 1 xor 1)
5 1 and 0 xor (6*4 and 0) or not(0 and 6)
6 1 and (1 xor not(5 xor 1 and 0)) xor not(1 xor not(1 or not(1)))

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/operators


Calculator Linking

One of the most important features of the TI graphing calculators is their linking, where they communicate with another TI calculator or a computer across a link cable that is connected between them. There are a few different link cables that TI has created, and they each have their own advantages and disadvantages:

  • Graph Link — This is the classic link cable that has been around since the TI-83 was first released. It works with every calculator before the TI-84+CE, and it comes in black (for the PCs) or gray (for the Macs). It works with the Graph Link software, which doesn't work very well with the newer calculators. The TI-84+CE no longer has an I/O port so this cable cannot be used to transfer data.
  • USB Link — This is the new link cable that is designed to be much faster, since it uses the USB port of a computer rather than the COMM port that Graph Link uses. Besides the port, it also only works with the TI Connect software instead of the Graph Link software.
  • Mini USB Link — This is only available on the newer TI-84+/SE calculators, since it actually uses the second smaller USB port on the TI-84+/SE calculator instead of the usual I/O port. It works pretty much the same way the USB Link does, and in fact uses the same TI Connect software.

In addition to the official link cables, you can also make your own using parts of other cables. Putting together a link cable is a rather delicate operation, and requires a considerable amount of knowledge of electronics and linking. This isn't recommended unless you know what you are doing — if you screw up, you can really mess up your calculator!

Calculator to Calculator

There are two commands that you can use when linking one calculator to another: GetCalc(, and Get(. The GetCalc( command was designed such that you can receive a variable from another calculator; unfortunately there are very specific requirements for the sending calculator to actually send the variable (it must be in a preemptible state like Pause or Menu(, and cannot be executing an assembly program). Whilst this can seem a difficult task to actually create a fully functional and fun multiplayer game, the multiplayer page shows workarounds to make such a program achievable — the key to which is fully understanding the nature of GetCalc(.

The Get( and Send( commands were created for use with the CBL (Calculator-Based Laboratory) and CBR (Calculator-Based Ranger) devices in math and science classes. These devices collect real-time data from various sensors that you can connect to them, and allow you to view and analyse the results. At the same time, they were originally used by the TI-82 calculator for receiving and sending variables respectively between calculators, and actually still operate in that capacity.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/linking


Controlling Program Flow

Controlling flow defines the order in which a program runs, what line of code will be executed next; to repeat or skip a group of commands. There are three main parts of controlling flow: conditionals, loops, and branching. Each of these parts is used in different situations and to serve different functions. Together they are an integral part of all programs.

When dealing with conditionals and loops, the decision whether the conditional or loop will be executed is based on Boolean Logic — the principle that something can only be true or false at any given time. While any nonzero value is evaluated to true (i.e. it will be executed), a zero value is evaluated to false (i.e. it will be skipped over, not executed).

Conditionals

Conditionals are used to make decisions in programs. The program can carry out different actions, depending on if certain conditions occur — directing the flow of program execution. Conditionals determine if code will be executed or not.

There are three different types of conditionals: If, If-Then, and If-Then-Else. There are certain advantages and disadvantages to each conditional, and there are also certain situations where each conditional should be used.

If Conditional

The first, and simplest, type of conditional is the If. It is used when you only want to execute one command. The If conditional needs the If command to work. The command that is immediately following the If conditional will be executed if the condition is true, but it won't be executed if the condition is false.

Format
:If condition
:Command

Because If conditionals are generally slow, you should replace them with Boolean conditionals when you are just changing a variable. You take the condition that is in the conditional, put parentheses around it, and multiply it by the value that you are changing the variable (the value should be left off when it is one since it is unnecessary).

:If X=3
:Y+2→Y
Use Boolean Conditional
:Y+2(X=3→Y

The reason that this works is the condition will evaluate to one if it is true and zero if it is false. Since this value is then multiplied by the value that you are changing the variable, the changing value will stay the same if the value is one but it will become zero if the value is zero. So, the Boolean conditional is faster than an If conditional when the condition is true, but it will be slower when the condition is false because zero is still stored to the variable.

Boolean conditionals also have another advantage over If conditionals. When you have several Boolean conditionals that deal with the same variable, you can combine them into one Boolean conditional. Boolean conditionals can have multiple conditions that change the variable by different values. If you change the variable by the same value in two or more conditions, you can factor the value out by multiplication. This works best with large values.

:A+5(K=26→A
:A-5(K=24→A
Combine Conditionals
:A+5((K=26)-(K=24→A

If-Then Conditional

The second type of conditional is the If-Then. It is used when you want to execute more than one command. Besides the If command, the If-Then conditional needs the Then and End commands to work. The Then command tells the calculator that there are multiple commands in the conditional to execute, while the End command signifies the end of the command block.

Format
:If condition
:Then
:Command(s)
:End

The commands immediately following the Then will be executed if the condition is true, but the commands won't be executed if the condition is false. Instead, program execution will continue after the End. Because If-then conditionals are twice as fast as If conditionals (they are larger, though, because of the added commands needed to use them), you might want to replace an If conditional with an If-Then conditional when speed is the top priority.

:If A=1
:Disp "Hello
Replace With If-Then Conditional
:If A=1:Then
:Disp "Hello
:End

With the If-Then and If-Then-Else conditionals, you can put conditionals inside of each other (known as nesting). You can also put loops inside conditionals. When you have two or more If conditionals that have a common condition (i.e. a compound condition made using the logic operators), you should take the common condition out, make it into an If-Then conditional, and nest the If conditionals inside it.

:If A=1 and B=1
:C+2→C
:If A=1 and B=2
:D+1→D
Take Out Common Condition
:If A=1:Then
:C+2(B=1→C
:D+(B=2→D
:End

This will speed up the program execution when the If-Then conditional is false. Instead of testing each If conditional and its conditions, the If-Then conditional (and the nested If conditionals) will be skipped over if the first condition is false. Remember to put the closing End command for the If-Then conditional, otherwise you will get an error.

If-Then-Else Conditional

The third, and last, type of conditional is the If-Then-Else. It is used when you want to execute one or more commands if a condition is true and one or more other commands if the condition is false. This is equivalent to two separate If-Then conditionals with opposite conditions, but it is faster because there is only one condition test (since only one of the conditions can be true at one time). Besides the If command, the If-Then-Else conditional needs the Then, Else, and End commands to work.

Format
:If condition
:Then
:Command(s)
:Else
:Command(s)
:End

The commands between the Then and Else will be executed if the condition is true, while the commands between the Else and End will be executed if the condition is false. This is an important part of If-Then-Else conditionals because it determines what order you put the commands, whether they should go in the true or false part of the conditional.

When using an If-Then-Else conditional and only one command is executed if the condition is true or false, you can replace the If-Then-Else conditional with a simple If conditional. You switch the order of the commands so the false command comes first (because that command will be executed by default), and place the If conditional between the two commands. This primarily works when the commands are store commands, but it also can be used when you are building a string of text that you display.

:If B:Then
:"Hello→Str1
:Else
:"Goodbye→Str1
:End
Replace with If conditional
:"Goodbye→Str1
:If B
:"Hello→Str1

To put the conditional commands in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press PRGM again and scroll over to CTL. The If, Then, and Else commands are in the first three spots (respectively), while the End command is in the seventh spot. You press ENTER to put the commands in your program.

Operators

Operators are used if you want to make compound conditions that are true depending on two or more conditions. When using operators, the left side is being compared to the right side. The operators can be used with any of the three different types of conditionals, as well as the Repeat and While loops.

There are two kinds of operators: conditional and logic. The six different conditional operators are: =, ≠, >, <, ≥, and ≤. The four different logic operators are: and, or, xor, and not. Conditional operators can be used (joined) with logic operators.

The =, ≠, >, <, ≥, and ≤ operators all compare and test two conditions. = returns true if the conditions are equal. ≠ returns true if the conditions are not equal. > returns true if the first condition is greater than the second condition. < returns true if the first condition is less than the second condition. ≥ returns true if the first condition is greater than or equal to the second condition. ≤ returns true if the first condition is less than or equal to the second condition.

Format
:If condition = condition
:If condition ≠ condition
:If condition > condition
:If condition < condition
:If condition ≥ condition
:If condition ≤ condition

The one instance where you don't need the ≠ conditional operator is when comparing a variable to zero. Because every nonzero value is treated as true, you don't need to compare if the variable's value is nonzero since any value will work. Instead, you can just put the variable by itself.

:If C≠0
Remove ≠ Operator
:If C

There is a simple truth table that is used to show how the logic operators work. The truth table is based on Boolean Logic, the principle that a condition can only be true or false. A true value is represented by one or any nonzero number. A false value is represented by zero. A and B are just conditions.

A B and or xor not(A)
1 1 1 1 0 0
0 1 0 1 1 1
1 0 0 1 1
0 0 0 0 0

The and, or, and xor operators compare and test two conditions, while the not operator only tests one. and returns true if both conditions are true. or returns true if one or both conditions are true. xor returns true if either condition is true (but not both). not returns true if the condition is false.

Format
:If condition and condition
:If condition or condition
:If condition xor condition
:If not(condition)

One way that the not operator can be used is for switching something from true to false or on to off, and vice versa. When dealing with a variable, not inverts the variable's value; so you should use not instead of comparing a variable to zero because not returns true when the variable is zero. At the same time, don't try to use not in every condition because there are many ways of writing a condition.

:If A=0
Use not Operator
:If not(A

The not operator is also used when applying DeMorgan's Law. DeMorgan's Law can be used for conditions in which there is an individual not operator around two separate unary conditions (i.e. they don't have conditional operators) joined by the and or or operators. It allows you to remove the second not operator and then change the and to or, and vice versa.

:If not(A) and not(B
Use DeMorgan's Law
:If not(A or B

The and and or operators can be replaced using math logic. Since and is only true when all the conditions are true, you can multiply the conditions together for the same effect (you can leave off the multiplication sign). Only one condition has to be true for or to be true, so adding the conditions together works as well. For conditions that have operators attached to them, you just put parentheses around them so they are treated as Boolean values. However, math logic is somewhat slower compared to the logic operators.

:If A and B
:If A or not(B
Replace Operators
:If AB
:If A+not(B

When using the and operator, if the first condition is false, the second condition will not be tested. The and and not operators have the highest importance (precedence) of the logical operators, so they are evaluated first. This is useful when you have a condition that combines the and and or operators (where the and operator comes first), because you don't need to include parentheses around the and operator. However, parentheses are sometimes needed simply to provide clarity.

:If (A=1 and B=2) or (A=2 and B=1)
Remove Parentheses
:If A=1 and B=2 or A=2 and B=1

To put the operators in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press 2nd and MATH. The conditional operators are in the TEST menu, while the logic operators are in the LOGIC menu. You press ENTER to put the commands in your program.

IS>( and DS<(

Two specialized conditional commands are available: IS>( and DS<(. These commands are equivalent to If conditionals, except the next command will be skipped when the condition is true. They have the variable update built-in, so they are smaller than using regular If conditionals.

The IS>( and DS<( commands each take two arguments, but they differ in functionality. The first argument is the variable, and it can be a real variable (A-Z or θ). The second argument is the value, and it can be either a number, variable, or expression.

IS>( adds one to the variable (increments it by one), and compares it to the value. The next command will be skipped if the variable is greater than the value, while the next command will be executed if the variable is less than or equal to the value.

Format
:IS>(variable,value)
:Command

DS<( subtracts one from the variable (decrements it by one), and compares it to the value. The next command will be skipped if the variable is less than the value, while the next command will be executed if the variable is greater than or equal to the value.

Format
:DS<(variable,value)
:Command

These commands are not without problems, however. Because the skipping feature is usually not needed, you will have to make sure that the value is always greater than (or less than) the variable, so that the next command is executed. This is not always possible to do. An undefined error will occur if the variable doesn't exist before the command is used, which happens when the DelVar command is used. Finally, these are not looping commands, so they shouldn't be used in that manner.

To put the IS>( and DS<( commands in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press PRGM again and scroll down the CTL menu until you find the commands. You press ENTER to put the commands in your program.

Loops

Loops cause a segment of code to repeat until a stated condition is met. Instead of having to write out something or do an action several times, you just do it once and put it inside a loop.

There are three different kinds of loops: For, While, and Repeat. There are certain advantages and disadvantages to each loop, and there are also certain situations where each loop should be used. For loops should be used when you know how many times the loop will be executed, whereas Repeat and While loops are the converse. The For loop is the fastest of the three loops.

For Loops

The For loop takes four arguments: the variable (A-Z or theta), the starting value, the ending value, and the increment. It counts from the starting value to the ending value at the specified increment.

The variable is used to keep track of how many times the For loop has been executed. Because it is set to the starting value when the For loop begins, you don't need to initialize the variable before. The ending value is the value that the variable ends at. The increment determines how much the variable's value will be increased each time through the loop. The default increment is 1, so the increment can be left off when it is 1 (it is optional). The increment can be positive or negative.

After each time the For loop is executed, the variable is checked to see if it is equal to or greater than the ending value. If the variable is, then the loop is exited and program execution continues after the End command. (The End command determines the boundaries of the loop.) If the variable isn't, the variable is incremented by the increment and the loop is executed again.

Format
:For(variable,start,end[,increment])
:Command(s)
:End

One of the common uses of For loops is making delays. Although you can use the Pause command, this brings the program to a halt and the user has to press ENTER to get out of it. With a For loop, you can make a small delay that will only last as long as you want it to last and it doesn't require the user to do anything. You just use an empty For loop (no commands inside of it). The larger the difference between the starting and ending values, the bigger the delay.

:For(X,1,200)
:End

Sometimes you might want to prematurely exit out of a For loop (stop it before it is completely finished). You can do this by changing the variable inside the loop. You just need to make the variable larger than the ending value.

:For(A,5,100)
:110→A
:End

To put the For loop command in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press PRGM again and scroll over to CTL. You then scroll down to For (or press the 4 key) and press ENTER. The End command can be found in the same menu, just lower at the seventh spot on the menu (press the 7 key).

While Loops

A While loop executes a block of commands between the While and End commands while the specified condition is true. The condition is tested at the beginning of the loop (when the While command is encountered), so the loop will be skipped entirely if the condition is false when the loop is first entered. To ensure that the loop will be executed, you need to declare the values of the variables in the condition before the loop.

After each time the While loop is executed, the condition is checked to see if it is false. If it is false, then the loop is exited and program execution continues after the End command. If the condition is true, the loop is executed again.

Format
:While condition
:Command(s)
:End

When using While loops, you have to provide the code to break out of the loop (it isn't built into the loop). If there is no code that ends the loop, then you will have an infinite loop. An infinite loop just keeps executing, until you have to manually exit the loop (by pressing the ON key). In the case that you actually want an infinite loop, you can just use 1 as the condition. Because 1 is always true (based on Boolean Logic), the loop will never end.

Format
:While 1
:Command(s)
:End

To put the While loop command in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press PRGM again and scroll over to CTL. You then scroll down to While (or press the 5 key) and press ENTER. The End command can be found in the same menu, just lower at the seventh spot on the menu (press the 7 key).

Repeat Loops

A Repeat loop executes a block of commands between the Repeat and End commands until the specified condition is true. The condition is tested at the end of the loop (when the End command is encountered), so the loop will always be executed at least once. This means that you sometimes don't have to declare or initialize the variables in the condition before the loop.

After each time the Repeat loop is executed, the condition is checked to see if it is true. If it is true, then the loop is exited and program execution continues after the End command. If the condition is false, the loop is executed again.

Format
:Repeat condition
:Command(s)
:End

When using Repeat loops, you have to provide the code to break out of the loop (it isn't built into the loop). If there is no code that ends the loop, then you will have an infinite loop. An infinite loop just keeps executing, until you have to manually exit the loop (by pressing the ON key). In the case that you actually want an infinite loop, you can just use 0 as the condition. Because 0 is always false (based on Boolean Logic), the loop will never end.

Format
:Repeat 0
:Command(s)
:End

To put the Repeat loop command in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press PRGM again and scroll over to CTL. You then scroll down to Repeat (or press the 6 key) and press ENTER. The End command can be found in the same menu, just lower at the seventh spot on the menu (press the 7 key).

Nesting Loops

One important aspect of loops is putting them inside other loops (known as nesting). Besides nesting any of the different kinds of loops inside each other, you can also nest loops inside conditionals. When nesting loops, you need to remember to put the appropriate number of End commands to close the loops.

The easiest way to keep track of lots of nested loops is to code the first part, add an End immediately after the conditional, and then hit [2ND][DEL] on the line with the End, then hit [ENTER] a lot of times.

Branching

Branching allows the calculator to jump from one point in a program to another. Sometimes you don't want every part of the program to be executed. You may want to skip over a certain part of a program if a certain condition occurs.

Branching uses the Lbl and Goto commands. Lbl and Goto work in pairs; you need to have both for branching to work. The Lbl command specifies a location in a program. The label can be any one or two alphanumeric character combination (from A-Z, 0-9, and θ), but ideally you want it to be only character to save memory. The Goto command causes program execution to jump to the specified label with the same character combination, and then continue from there.

Format
:Lbl character1[character2]
:Goto character1[character2]

When using branching, you have to provide the break-out code (it isn't built-in). If there is no code that ends the branching, then program execution will continue indefinitely, until you manually exit it (by pressing the ON key). If conditionals are commonly used, but in the case you want infinite branching, you should instead use a While or Repeat loop.

:Lbl A
:Goto A
Replace with Loop
:Repeat 0
:End

To put the Lbl and Goto commands in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press PRGM again and scroll over to CTL. You then scroll down to Lbl (or press the 9 key) and press ENTER. The Goto command can be found in the same menu, just lower at the tenth spot (press the 0 key).

Disadvantages of Branching

Although branching may seem like a good alternative to loops, it should be used sparingly. Branching should only be used when a loop isn't practical and when something only happens once or twice. This is because branching has several disadvantages associated with it.

The biggest disadvantage of branching is that it's slow. When the calculator reaches a Goto command, it stores the label name in memory and goes to the beginning of the program. It then searches through the program until it finds the Lbl command with the matching label name. If the label is deep within the program and you have a large program, this can bring the program to a crawl.

Another disadvantage of branching is that it can lead to memory leaks when used to exit conditionals or loops (anything that uses an End command). The calculator stores the End command in memory, and it is only released when the calculator reaches it.

If the conditional or loop is exited with branching, however, the End command is never released from memory, and the calculator will continue using that memory. If this is done enough times, the calculator will eventually run out of memory, causing a memory leak. When there's less memory, the program also runs more slowly. Memory leaks don't have any real affect on the calculator, as the memory is released when the program exits.

The last disadvantage of branching is that it makes program code difficult to read and maintain. While loops are straightforward, following a set pattern, branching can lead to anywhere in a program. Trying to figure out how branching affects the program code can cause some serious headaches.

Reworking Branching to Remove Memory Leaks

One of the simplest memory leaks that occurs is using branching to exit out of a loop when a certain condition of an If conditional is true. If the loop is an infinite loop (i.e. Repeat 0 or While 1), you should take the condition from the If conditional and place it as the condition of the loop. This allows you to remove the branching, since it is now unnecessary.

:Repeat 0
:getKey→B
:If B:Goto A
:End:Lbl A
Place Condition in Loop
:Repeat B
:getKey→B
:End

Of course, the only reason that this memory leak fix is possible is because of the If conditional (since the If conditional doesn't need a closing End command). When dealing with an If-Then or If-Then-Else conditional, you will have to rework the conditionals so the branching has its own If conditional. Depending on how many commands there are in the conditionals, you might be able to just use an If conditional or you might need to use an If-Then conditional.

:If B:Then
:Disp "Hello
:Goto A
:End
Use Separate If Conditionals
:If B
:Disp "Hello
:If B
:Goto A

This memory leak fix will work most of the time, but it isn't applicable when one of the values of the variables in the condition is changed by one of the commands inside the condition. The way to get around this is by using another variable for the If conditional that the branching uses. You initialize the variable to zero, assign the variable whatever value you want in the conditional, and then check to see if the variable is equal to that value in the branching conditional.

:If A=1:Then
:3→A:4→B
:Goto A
:End
Use Another Variable
:Delvar CIf A=1:Then
:3→A:4→B:π→C
:End
:If C=π
:Goto A

So What Is Branching Good For?

Despite its many disadvantages, Lbl and Goto statements actually have their uses. For example, you may want to have a label at the end of the program that you Goto everywhere you want to exit the program. This is useful if you have a lot of clean-up (such as deleting large temporary variables) every time the program exits.

If K=45:Goto Q
...
Lbl Q
DelVar [A]DelVar L1
ClrHome

Goto statements are also good in programs that call themselves very many times. Every time a Repeat or While statement is encountered, the program has to set aside a portion of memory to remember about that statement. In recursive programs, this can add up (a good example is a recursive program to fill in an arbitrary shape). Gotos require no such overhead, and if the program is small, they're not as slow as they are in larger programs.

Just remember that since Goto-Lbl constructs are slow when the label is far from the beginning of the program, and you shouldn't use them in speed-critical situations. Also, they make your program hard to read for when you or anyone else edits it, especially if they jump backwards.

Subprograms

Subprograms are programs called from inside other programs (at any time while the program is running). Although they are listed in the program menu and can be executed independently like any other program, subprograms are primarily designed to do a particular task for the other program.

The prgm command is used to execute another program as a subprogram. You insert the prgm command into the program where you want the subprogram to run, and then type (with the alpha-lock on) the program name. You can also go to the program menu to choose a program, pressing ENTER to paste the program name into your program.

Format
:prgmname

To create a subprogram, you take the code from the parent program and put it in a new program. When naming your subprograms, you should try to name them Zparentn or θparentn, where parent is the name of the parent program and n is the number (if you have more than one). Because subprograms are relatively unimportant by themselves, you want them to appear at the bottom of the program menu.

When the subprogram name is encountered during a program, the program will be put on hold and program execution will transfer to the subprogram. Once the subprogram is finished, program execution will go back to the program, continuing right after the subprogram name.

Although subprograms can call themselves or other subprograms, this should be done sparingly because it can cause memory leaks if done too much or if the subprogram doesn't return to the parent program. Branching is local to each program, so you can’t use Goto in one program to jump to a Lbl in another program. All variables are global, so changing a variable in one program affects the variable everywhere else.

To put the prgm command in your program, you need to first be in the Program editor. You press PRGM and then scroll over to EDIT. Once in your program, you press PRGM again and scroll over to CTL. You then scroll down until you get to the prgm command, and press ENTER to put the command in your program.

Advantages & Disadvantages of Subprograms

There are several advantages of using subprograms. First, and foremost, subprograms reduce program size by eliminating redundant code. Instead of having to type the code multiple times for a task that occurs more than once in a program, you just type it once and put it in a subprogram. You then call the subprogram whenever you want to perform the task in your program.

Second, subprograms increase program speed by making programs as compact as possible. You separate conditional tasks from the program (they either happen every time or they are skipped over), and put them in a subprogram; you then call the subprogram instead. This improves program speed because the calculator doesn't have to go through all of the conditional code anymore.

Third, subprograms make editing, debugging, and optimizing easier. Instead of going through the entire program, looking for the code you want to change, you can focus on one subprogram at a time. This makes the code more manageable, allowing you to more thoroughly look at each subprogram and to better keep track of which subprograms you have looked at.

Lastly, subprograms are reusable, allowing multiple programs to share and use the same code. Breaking a program into smaller, individual subprograms, which each do a basic function or task, allows other programs to use those subprograms. Consequently, this reduces program size.

The primary disadvantage of subprograms is that there are additional programs that the user needs to use your program. If you give someone your program, you will have to also give them your subprograms. Your program won't work properly anymore if somebody deletes your subprograms or forgets to include them with your program. Although this is mostly out of your hands, users will think your program is at fault.

The simple solution to this problem is to put the subprogram back in your program when you finish it. This should only be done if the subprogram was just used once or twice and it won't slow the program down. All you have to do is paste the code from the subprogram in place of the program call. You could also put all of the programs used into a group and distribute it as so.

Exiting Programs

Exiting programs (terminating the execution of a program) is done with the Return and Stop commands. The two commands are different and each have advantages.

In most cases, Return and Stop both stop program execution and return to the homescreen (even from inside loops). Return and Stop function differently, however, when used in subprograms. The Return command will stop the subprogram, and program execution will resume in the calling program after the line where the subprogram was called. In contrast, Stop will stop both the subprogram and any calling programs and go to the homescreen. Return should generally be used instead of Stop because old versions of some utilities such as DCS cannot safely run programs with the Stop command.

:ClrHome
:Input "Guess:",A
:Stop
Replace Stop with Return
:ClrHome
:Input "Guess:",A
:Return

When the calculator reaches the end of a program, it will automatically stop executing as if it had encountered a Return; therefore, Return is unnecessary on the last line of a program.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/controlflow


User Settings
MODE.PNG FORMAT.PNG TBLSET.PNG

The TI-83 series of calculators has many options to select from that influence either the effect of commands or the way numbers or graphs are displayed. Outside a program, these can be changed by accessing the Mode, Format, or TblSet screens (shown above), and selecting the correct options. When editing a program, going to these screens and choosing an option will instead paste a command that sets that option for you.

These commands are given below, divided by the screen where it is found:

Mode Settings (MODE)

Graph Format Settings (2nd FORMAT)

  • RectGC and PolarGC determine how coordinates of the cursor are displayed and stored.
  • CoordOn and CoordOff determine whether the coordinates of the cursor are displayed at all.
  • GridOn and GridOff determine whether the grid is displayed.
  • AxesOn and AxesOff determine whether the X and Y axes are displayed.
  • LabelOn and LabelOff determine whether the X and Y axes are labeled (if they are displayed)
  • ExprOn and ExprOff determine whether the equation graphed or traced is displayed.
  • Time, Web, uvAxes, uwAxes, and vwAxes (visible in Seq mode) determine the way sequences are graphed, the default being Time.

Table Settings (2nd TBLSET)

  • IndpntAuto and IndpntAsk determine whether values of the independent variable in the table are calculated automatically.
  • DependAuto and DependAsk determine whether the values in the table are calculated automatically for all equations.

Miscellaneous Settings (2nd CATALOG)

Using these settings in a program

A fair amount of these settings are important to programmers because, if set to the wrong value, they can easily mess up the program. At the beginning of the program, therefore, it's a good idea to set these settings to the correct value. At the very minimum, programs that use the graph screen should set AxesOff if necessary, since AxesOn is the default and a very common setting. This is a part of program setup.

However, another important consideration is that it's somewhat rude to change the user's settings without permission, so your program should change as little as possible. How to reconcile these diametrically opposite goals? There are several ways that work for different settings:

Use GDBs (Graph DataBases)

The graph screen settings can be backed up in (and retrieved from) a GDB file by the StoreGDB and RecallGDB commands. If you store to a GDB at the beginning of the program, and recall from it at the end, you will have preserved all settings that deal with the graph screen.

Change math settings implicitly

Instead of changing settings like the Degree/Radian or the Real/a+bi setting, you can use certain commands that will force calculations to be done with that setting regardless of the mode. For example, you can use the degree symbol or radian symbol to make ambiguous calculations like sin(30) into unambiguous ones like sin(30o). Similarly, by adding 0i to a number, you force it to be complex, so that calculations done with it will never cause an ERR:NONREAL ANS (even if you're in Real mode).

Ignore uncommon settings

You might ignore settings that are too uncommon to matter. For example, setting the Full command is unnecessary, because very few people would ever use a split screen, and people that do probably will also figure out why your program breaks when they do so.

Be rude when you must

For something like Float, there's no way to avoid changing the user's settings in a way you can't restore. If you have to change a setting so your program works, do it, and mention the issue in the readme. If you changed a setting to an uncommon value, change it back to "Float" (in general, to the default value) when you're done.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/settings


Memory Management

The TI-83 and TI-84 series of calculators feature a considerable amount of memory available for storing variables, programs, groups, and even assembly applications (the last two are only available on the TI-83+/TI-84+/SE calculators). However, as you start putting those things on the calculator, the memory slowly gets used up, and if you don't do anything, the calculator will eventually run out of memory — giving you the dreaded ERR:MEMORY error.

Before getting into memory management, it is important that you know there is a major difference between the TI-83 calculator and the rest of the TI-83 and TI-84 series of calculators. In particular, the TI-83 just has RAM (Random Access Memory) memory, while the rest of the calculators have RAM memory as well as Flash ROM (Read-Only Memory) memory, also known as archive memory.

RAM is the faster memory of the two, and it is what is primarily used whenever you run a program. Its one downfall is that it tends to get cleared very easily after crashes. Most people have probably noticed this when their calculator crashed, and they turned it back on, and it said RAM cleared. In addition, variables in RAM can be overwritten accidentally by a program that uses them.

Flash ROM, on the other hand, is the more reliable memory, and it is what is used when you want to store a program for long-term. Its one downfall is that you can't access something stored in ROM. The only exception to this is assembly programs and applications, which are programmed in the calculator's own programming language and thus can access anything on the calculator.

There are several different commands you can use for managing your calculator's memory:

  • DelVar — DelVar is useful for deleting variables, which is the most obvious way to manage memory, and it is what most people are interested in. The DelVar command can delete any variable that you want, with exception to specific elements of a matrix or string or system variables.
  • ClrList/ClrAllLists — Similar to DelVar, ClrList and ClrAllLists only work with lists and they set the dimensions of one list or all lists to zero respectively. This essentially causes the list(s) to be deleted, since you can't do anything with a zero element list.
  • Clear Entries — When executing programs or doing math on the calculator's home screen, the calculator keeps a history of these entries (you can cycle through them by pressing 2nd ENTER). If you do a lot of stuff on the home screen, the entries history can become rather large.
  • Archive/UnArchive — When using variables and programs, you need to move them from archive to RAM; and when you are done using them, you move them back to archive. While you can archive programs on the home screen, that is not possible from inside a program (although you can use an assembly library to do that).
  • GarbageCollect — As you archive and unarchive variables and programs, the calculator keeps storing things until it eventually needs to clean the archive memory. Rather than simply leaving this until the calculator finally forces you to do it, which takes a fair amount of time, you can run the GarbageCollect command periodically.

Since the TI-83 calculator only has RAM memory, it does not have the Archive, UnArchive, and GarbageCollect commands. If you plan on porting a program to the TI-83, you shouldn't use any of these commands, since they will cause the program to be corrupted. In the case of lists, however you can use the SetUpEditor command instead of UnArchive to get around this problem.
Also note that trying to use DelVar or ClrList with an archived variable does not work, and will actually return an ERR:ARCHIVED error.

Accessing the Memory Menu

When accessing a variable or program from the memory menu, you press 2nd MEM. You then select 2:Mem Mgmt/Del and press one to display a scrollable list of all the files on the calculator. You use the up and down keys to move the cursor on the left. On the top lines of the screen you will see how much free RAM and ARC (archive) memory there is.

Once you have found a file you want to delete, press DEL. If the file is not a variable, the calculator will prompt you to confirm the deletion, and you have to select 2:Yes. Once you have found a file you want to archive, press ENTER. An asterisk will appear to the left of the file name, indicating that it is archived. Some files, such as applications, will not allow you to unarchive them since they can only reside in ROM.

Archiving may sometimes not be possible, however, if the calculator does not have sufficient free ROM available. This occurs primarily when a person can't bring themselves to delete a file because they feel like every file is important. At this point, the only option is to delete some files off of their calculator to make room. As part of memory management, a good policy is to keep the calculator's memory organized and to delete any files that you don't need.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/memory-management


Time And Date Commands

The TI-84 Plus and TI-84 Plus SE, which have a built-in hardware clock, introduce several commands for dealing with time. Some of these rely on the built-in clock, while others are used for formatting times and dates and could technically have been introduced on earlier calculators. However, the only time/date command that is available on the pre-84 calculators is dbd(.

All of these commands except dbd( can be found only through the command catalog (2nd CATALOG). dbd( can also be found in the Finance menu — 2nd FINANCE on the TI-83, and APPS 1:Finance… on the TI-83+ or higher.

Despite its name, the Time command has nothing to do with the clock. It is a mode setting for sequence graphs.

Low-Level Commands

  • startTmr — This command returns the current value of a timer that is updated every second when the clock is enabled. This value doesn't correspond to any actual time, but can be used with checkTmr( to get a time difference.
  • checkTmr( — checkTmr(X) is equivalent to startTmr-X. This can be used to get the time elapsed since startTmr was used.
  • ClockOn, ClockOff — Enables or disables the hardware clock.
  • isClockOn — Tests if the clock is enabled or not.

Time Commands

  • setTime( — Sets the current time, in hours, minutes, and seconds. If the clock is enabled, this time will be updated every second.
  • getTime — Returns the current time as the list {hours, minutes, seconds}. This command is unaffected by time format.
  • setTmFmt( — Sets the time format - 12 hour, or 24 hour.
  • getTmFmt — Returns this time format setting.
  • getTmStr( — Returns the current time as a string, affected by time format (though you can override it with an optional argument).

Date Commands

  • setDate( — Sets the current date (year, month, and day). If the clock is enabled, this date will be updated as needed.
  • getDate — Returns the current date as the list {year, month, day}. This command is unaffected by date format.
  • setDtFmt( — Sets the date format - 1 for month/day/year, 2 for day/month/year, or 3 for year/month/day.
  • getDtFmt( — Returns this date format setting.
  • getDtStr( — Returns the current date as a string, affected by date format (though you can override it with an optional argument).

Time/Date Manipulation

  • timeCnv( — Converts a number of seconds into a list of {days, hours, minutes, seconds} representing the same time lapse.
  • dayOfWk( — Returns the day of week (Sunday through Saturday encoded as 1 through 7) of a specified date.
  • dbd( — Returns the number of days between two dates — this command is available on all calculators, not just the 84+/SE.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/time-and-date


Planning Programs
toolbar-separator.png This article is part of the planning stage of the development cycle.

Before writing any of the code for a program, you should carefully plan out the program. This may seem like an unnecessary step, time that could be better spent, but it will pay major dividends in the end. Planning not only results in better quality programs, but many times it will also cut down the coding time (since you don't have to waste time rewriting the program) — a win-win situation!

The first thing you want to do when planning a program is to decide what the program will do. Beginner programmers often say that they want to create a cool game, but they don't get much farther than that. For them to have a real chance of creating their program, they need to determine what the objective of the program will be, and then build off of that. For program ideas, see the project-ideas page.

When coming up with an idea for a program, you should try to be realistic about the limitations of TI-Basic, and what a program can and can not do. For example, a game that needs lots of speed to be worthwhile for the user to play, such as Phoenix or Mario, really isn't very practical in TI-Basic beyond only moving a few things on the screen at any one time. In addition to speed, TI-Basic also suffers from limited graphics capabilities.

Once you have determined what the program will do, you need to decide what features the program will have. This can include: potential program options, the interface (home screen or graph screen), main menu, an about screen, user help, and any other things you may want. The more thorough you are with planning your program, the easier the coding will be; it is to your benefit to do a good job.

If you can't come up with any ideas for your program or you are unsure of if the ideas that you have come up with make sense, you should get input from the TI community. The four most friendly, active user forums are:

Since these are some of the people who will be using your program when it is finished, you should ask them to evaluate your program concept and to offer some constructive criticism. They might also be able to give you some new ideas that you never thought of.

Even if you thoroughly plan a program and get community input, it's simply not possible to think of everything up front. While making changes later on when a program is in heavy development can be a lot more work than making those changes at the beginning, there's nothing wrong with changing or modifying your plans, if you believe the program will be better with the change(s).

Research Before Coding

Before doing any coding, you should do some research to determine what the best algorithms are for use in your program. One of the most common problems is a poorly though out algorithm, which may not work properly with other parts of the program.

When you do research you ensure that the algorithm is appropriate and that it will work effectively. This helps eliminate flaws in your algorithm, which can cause a multitude of errors if left unfixed. If you think your program through before you start coding, you can save yourself lots of time because you don't have to do several rounds of testing and debugging to get your program to work the way it should.

One of the ways to test an algorithm and how effective it will be in your program is to take a very small problem and trace by hand how your chosen algorithm would work in that situation. This allows you to see if the algorithm will actually work in the given situation.

If the algorithm doesn't work, you can immediately start looking for another algorithm. This saves you lots of potential time because you would have to come up with another algorithm had you just started coding it. Only when you are confident with the algorithm should you start the coding.

Translate It Into Pseudocode

The next step in the process is turning the program plans into pseudocode. Psuedocode involves using English (or whatever language you speak) in place of the TI-Basic code to describe what the program will do to perform the desired functions and tasks. This prevents you from getting caught up in the TI-Basic syntax, allowing you to more clearly focus on the program.

You should first start by looking at the big picture of the program and then break it down into smaller and smaller details. Using an outline as the base, this means you would put the most important things first and then gradually add everything else. This allows you to mentally picture what the program is going to look like and to make sure you don't forget anything. Remember to leave many times more space than you think you'll need for an outline, you'll probably end up discovering a few areas you hadn't thought of yet that need to be taken care of.

An important part of creating useful pseudocode is adding comments throughout. It is very easy to get lost in your logic or have problems come up that you don't have any idea on how to resolve. Besides telling you what the code is supposed to do (i.e. making coding easier), it will also force you to slow down and think through the logic of your program. Still, comments are only as good as you make them.

Use Many Small Programs While Coding

A single large program quickly becomes unwieldy and difficult to manage. While you're still editing the program, it's best to keep it in many small pieces. When you're done, you can combine them into one program again.

One of the benefits of this approach is that you can convert pseudocode into a main program almost right away. For example, imagine this pseudocode program:

Main Menu - user enters difficulty, etc.
Initialize variables
Main Loop:
 Player movement
 Draw player
 Enemy movement
 Draw enemy
 Check Win/Loss Condition
End Main Loop
If we won the game
 Display win message
Otherwise
 Display loss message
Cleanup

You could translate this into a basic program almost directly. Here's how we do it (note that we don't write any code yet):

prgmMAINMENU  // user enters difficulty, etc.
prgmINITVARS  // initialize variables
Repeat Z
prgmMOVEPLR  // moves player
prgmDRAWPLR  // draws player
prgmMOVENMY  // moves enemy
prgmDRAWNMY  // draws enemy
prgmWINLOSE  // sets Z to 1 or 2 if we won or lost
End
If Z=1:Then  // we won
prgmWEWON  // says "You win!"
Else
prgmWELOST  // says "You lose!"
End
prgmCLEANUP  // delete used variables

As you progress in writing the actual code, you create and edit each individual program (for example, you would create and edit prgmMAINMENU and write a menu in that program). Of course, if these sub-programs are big enough, you can split them up into their own sub-sub-programs in the same way.

When all the subprograms are finished, the program will work as it is, in 50 or so pieces (so you can test for bugs and tweak the individual programs). However, if you want to release your program, you probably don't want there to be 50 small programs to send. You can use the Recall feature (press [2nd][STO] to get to it) to combine the programs.

Go through the main program. Every time you get to a sub-program call, clear that line and press [2nd][STO]. The Recall option will come up. Press the [PRGM] key and select the appropriate sub-program from the EXEC menu. The calculator will paste that sub-program into the main program. When you're done, all the code is in your main program (and you can delete the now-unnecessary sub-programs)!

<< Creating New Program Versions Overview Portability >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/plan


Commenting Your Code
toolbar-separator.png This article is part of the coding stage of the development cycle.

When you are in the process of writing a program, everything about the program (i.e., variables, program structure, branching labels, etc.) is fresh in your mind and it's easy to remember. But what would happen if you stopped working on the program for a year, and then decided to start working on it again?

All or most of your previous knowledge of the program would be gone, and you would have to spend some time (or lots of time, depending on the program) to figure out how the program works again. While this is only a hypothetical example, this problem is a real concern for lots of people who have multiple projects going at any one time.

Thankfully, this problem can be easily prevented by simply adding comments to your code. A comment is a brief note that describes some functionality or feature of your code. You don't need to comment everything, but the two main things that you should comment are:

  • Program Structure — Loops and branching with appropriate label names
  • Variables — What their purpose is and any possible values

The amount of free RAM is the only limit on comment size, but you should generally try to keep your comments clear and concise. In addition, if your comment is more than a couple lines in length, you should split it up into multiple lines. This makes it easier to read and update, if needed.

Text Comments

There are a couple different ways that you can add text comments to your code, with each having their own advantages and disadvantages. The first way is to make the comment a string literal (i.e., place a quote before the comment text), and then just place it on its own line.

:"Comment here

The advantage of this comment method is that it is extremely simple to use and update. You can make your comment almost anything you want (the two characters you can't use are the store command and a quote), and the calculator just reads it as a string.

The disadvantage of this method is that it prevents you from using the Ans variable, since the comment will be stored to Ans when the calculator reads it. The comment also slows the program down because the calculator has to execute it each time.

The second way to add a text comment to your code is by placing the comment in a conditional or loop, and using zero as the condition. Based on Boolean logic, the condition will always be false, which causes the calculator to not execute the conditional or loop, and subsequently skip right over the comment nested inside of it.

:While 0
:Comment here
:End

The advantage of this comment method is that it doesn't mess with any of the variables, and you can use the store command and quote character. The disadvantage is that it takes up some additional memory to use the conditional or loop, and this problem only worsens the more comments you use.

Indenting Code

Another way to comment code is by indenting it, which allows you to easily identify control structures and blocks of code. Just like how there is a built-in colon that denotes the beginning of each new line, you can place your own colons before any statements on a line.

:While 1
::Disp "Hello
::Disp "Goodbye
:End

Although there is no restriction on how many colons you can place at the beginning of a line, one colon is generally sufficient. However, if adding two or three colons helps you better visualize the code, then that's what you should go with.

It is usually discouraged to use this method. Not only does it take up additional memory by adding bytes to the program, it also affects some commands. For example, the following method will not work. The intention of the code is to display only "FALSE".

:2→A
:If A=1
::Disp "TRUE"
:Disp "FALSE"

By adding the extra colon, an extra line is added. This specific line is skipped due to the If statement being false. However, Disp "TRUE" is run as well as Disp "FALSE".

Descriptive Variables

Yet another way to comment code is by using descriptive variables that reflect where and how they are used. This is primarily related to using the real variables (A-Z and θ), since they are the most commonly used variables, and are much smaller and faster than other variables.

Of the real variables, the standard variables and situations are:

  • I and J for the looping variable in For( loops
  • X and Y for the X and Y screen coordinates respectively.
  • K for storing the keypress with the getKey command.

Each of these variables is mnemonic — for example, K is the first letter in keypress — making them fairly easy to remember.

Advanced Uses

You can modify the text comments so that you can turn them on or off. You just use a conditional with a variable as the condition, and then change its value from false (i.e., the comments are off) to true (i.e., the comments are on). Based on Boolean logic, the easiest system for the variable value is one for true and zero for false.

You also need to display the comments on the screen, so that you can read them during program execution. If you are using the home screen, you should use the Pause command and its optional argument. While program execution is halted until the user presses ENTER, the Pause command allows you to display the entire comment on one line, and you can even scroll the comment left or right to read it, if necessary.

:If A:Pause "Comment here

You should use the same variable for all of the comments, so that the comments work in unison. The variable can be whatever you want, but the simplest variable to use is a real variable (A-Z and θ). You just need to remember to set the variable to zero at the beginning of the program, so that the comments are turned off by default.

<< Techniques Overview Subprograms >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/comments


Code Conventions
toolbar-separator.png This article is part of the coding stage of the development cycle.

Code conventions are a set of guidelines for writing programs, primarily focusing on the structure and appearance of the code. Although code conventions are generally subjective and informal, just the individual preferences of each programmer developed over time, there are several common conventions that most programmers follow and are considered to constitute good programming practice.

Following code conventions not only makes your code consistent, helping to make it easier to read and understand, but also eliminates a lot of the difficulty in maintaining it. Code conventions are also important in group projects, where multiple people are working together and everybody needs to be on the same page.

Naming

The general convention for naming programs, subprograms, labels, and custom lists is to choose a name that tells you what it is (in the case of programs and subprograms) or that relates to how it is used (in the case of labels and lists).

For example, if your program is a Minesweeper clone, then a good program name is something like MINES. If your MINES program has a subprogram, start it with θ or Z so that it appears at the bottom of the program list.

If you have a highscore function built-in to your game, then you should use a custom list that is related to your program's name (i.e., LMINE would make sense for the MINES game mentioned above).

In the case of a label name, you should make it mnemonic — Lbl UP would be an appropriate choice for the code that moves the screen up.

Formatting

The general convention for formatting code is to place related statements together on the same line. This is most applicable with variable declarations, If-Then conditionals, and short loops, although you can certainly put whatever statements that you want.

The way you get multiple statements on the same line is by separating each one with a colon, which is also used to denote the beginning of each new line. The program editor on the calculator allows sixteen characters per line, so if the statements are wider than that, they will cause the line to wrap around to the next line (and however many more lines are needed).

Structure

The general convention for structuring code is to use a loop, except for those situations where using a loop is impractical; in those cases, using a Goto is the preferred convention.

When deciding which loop to use, you need to look at what its functionality will be. If you want the loop to be executed a set number of times, then you should use a For( loop. If you want the code inside of the loop to be executed at least once, then you should use a Repeat loop.

The While loop is very similar to the Repeat loop, so the way to decide when to use either one is by thinking of the loop condition. If the loop is going to keep running as long as the condition is true, then you should use a While loop. If the loop is going to run until the condition is true, then you should use a Repeat loop.

Variables

The general convention for using variables is to use the most appropriate variable whenever possible. There are several different kinds of variables available, including reals, lists, matrices, and strings, and they each have their own time and place.

Reals are used for keeping track of one value, and because they are both small and fast, you should use them before using other variables. Lists are used for keeping track of multiple values, and because they can be created, you should use them for saving highscores and other important data.

Matrices are used for keeping track of two-dimensional values, which means you should use them for making maps on the screen. Strings are used for keeping track of characters, which means you should use them when you want to display text on the screen.

Sample Program

The following sample program is a modified form of the program on the movement page. The main things you should notice are the real variables grouped together on the first line and the use of the Repeat loops for the code structure.

PROGRAM:MOVEMENT
:4→A:8→B
:Repeat K=105
:Output(A,Ans,"X
:Repeat Ans:getKey→K:End
:Output(A,B," "
:A+(Ans=34)-(Ans=25
:Ans+8(not(Ans)-(Ans=9→A
:B+(K=26)-(K=24
:Ans+16(not(Ans)-(Ans=17→B
:End
<< Program Setup Overview Techniques >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/code-conventions


Debugging Programs
toolbar-separator.png This article is part of the revising stage of the development cycle.

Going through the process of debugging your programs may seem like a lot of unnecessary work, but it is better that you find and correct the errors then having the user of your program tell you that your program doesn't work. On this page, we've tried to simplify debugging for you by breaking it down into general steps that you can follow. Just remember to always strive for bug-free programs.

Backup & Document

Before debugging, make a backup of your program. This is to ensure that you don't lose your program in its current form. During the debugging process it is easy to mess up your program, overwriting or deleting necessary pieces of code. If you just spent several hours working on your program, you don't want to have all of that work wasted.

You should also backup your program before changing anything. This is so you will have a version of your program that you can return to if you mess up your program while doing further debugging. Instead of having to undo any coding mistakes that you made, you can just go back to the last updated version of your program.

You also want to document your program and the variables you use. This is important because it makes it easier to come back to the program in the future (if you need to). Documenting a program entails listing what the program does, how it does it, and anything else that might be important. For documenting the variables, you should list out all of the variables, including what they are used for and what values they can have.

Simplify the Code

You want to remove any code that is not related to the problem. If you are unsure of what code is related to the problem, look at what its function is. If the code is changing variables or controlling program flow, then it may be important to keep it. If it is just print statements or checking conditionals, you can probably remove it without it affecting the code.

Once you have identified the code that contains the error, you will want to create a new program and put the code in it. If the error still exists, you will want to remove parts of the code, repeatedly testing the code afterwards each time. If the error disappears, you know that the last part of the code that you removed is what caused the error.

One of the most common problems that programmers make when debugging their code is making lots of changes at once. This is usually not very effective because it can lead to other problems within the code or, if it results in removing some of the errors, you don't know which changes corrected the errors. It also tends to make the debugging process very unorganized because you will have to re-test parts of the code, and sometimes you won't even know which parts need to be re-tested. What you should do instead is fix each problem individually and then test the program. This will take you longer, but your program will have fewer errors and problems.

This can further be improved upon by breaking the program up into modules, testing and debugging the individual modules separately from the main program. The advantage of testing the modules by themselves is that it is easier to find errors. Instead of having to look at the whole program, you can look at an isolated part. Once you have removed all of the errors in the module, you don't have to test it again. After going through all of the modules, you then just have to debug the main program that calls the modules.

Analyze The Error

When you are trying to fix an error in your program, you will want to gather as much data about it as possible. To do this you should run your program several times, keeping track of when the error occurs, where it is happening, and what type of error it is.

Once you think you have a solid grasp of the error, you will want to repeatedly test the code that contains the error. If you can consistently produce the error, you will know that you are on the right track to fixing it. If you can't produce the error, however, that means you need to do more extensive analysis.

One of the most effective ways of debugging programs is to walk through the code. This involves sitting down with a printed version of the program, carefully going through its logic. Walking through the code will allow you to see potential solutions to the errors in your program.

There's another way to figure out where your bugs start, especially with Lbl errors. Place equations such as 1/4 around the path of the problematic code. Make every equation different. When the game crashes or acts up, go to the home screen and recall Ans. Whatever number Ans shows you (for our example, it would be .25) is where the code goes awry. Go to that part of the code and run further testing.

Once you have a potential solution, you will want to look at how it should work in the code, and then test it to see if it actually works like you believe. The more thorough you are at analyzing the solution, the easier it will be to tell if it will fix the error. Once you know that the solution will fix the problem, you can then apply it to your program.

Looking at the variables and their values is essential when you are debugging. You will want to take note of how they gradually change throughout the program. If you know which part of the program contains the error, you can then check the variables that are used within that part. Make sure the variables contain values within their correct limits. If they don't, you need to go to the code before and after the error, and check the value of the variables. Make sure the variables are functioning properly, and that you aren't doing anything to change them.

When writing code you will often make assumptions about it. You need to be aware of these assumptions when you are debugging, so you can make sure they are sound. If your program is not functioning properly, you should test all of your assumptions. One of the most common assumptions that programmers make is that the variables they are using are working properly. Most programmers will thoroughly debug their code, but they're not as thorough when debugging variables. Debugging can become very frustrating if you don't thoroughly debug both.

Debugging Tools

When you first start debugging your programs, you will want to check to see that the errors you are getting aren't because of a misuse of a command or a misunderstanding of a command's arguments. You should consult the TI-83+ manual to see what the syntax of the command is and how to use it properly. Many errors that you recieve can easily be remedied if you just consult the manual. In fact, if you use the manual when you are programming your program, you can avoid a lot of the typos and superficial errors during debugging.

The TI-Basic language has a rather useful feature for debugging programs: when it comes across an error while running your program, it will give you an error menu — telling you what the error is and giving you the option to see where the error is in your code. You will want to take the information that it gives you, and then see if you can figure out why it's producing an error.

After the error occurs, you should recall some of your variable's values to see what they are. This might give you an indication of what the error is (if a variable is not in the range it's supposed to be), where in a For( loop you are (just recall the variable you used for the loop), and many other helpful hints.

Many times you will make a simple mistake, such as forgetting to close a string or leaving an argument off of a command. You have to be careful, though, because sometimes the error that the calculator reports isn't the actual error in your code. You might have errors in your code that the calculator doesn't notice because it is still valid code, and it isn't until later that the errors cause problems. These errors are very hard to track down.

Using print statements is one of the oldest and most tested methods for debugging programs. If you come upon a problem in your program, and you can't seem to figure out what's causing it, you should add several print statements throughout the code. When you run your program, you will be able to see what is actually happening. You can do this to see the code that the program is running or to see what values the variables have.

If you don't like using print statements or you think they aren't effective enough, an alternative that you can try is inserting breakpoints (pause statements). Once you think you have identified the code that has the error, you can set breakpoints around it. After restarting the program, look at what happens to the code before and after the breakpoints. If this doesn't give you enough information about the error, you might need to use more breakpoints. The advantage of using breakpoints is that you can pause the execution of your program, allowing you to slowly look at the program and at what's causing the error. Two of the best places to put breakpoints are in program flow statements and inside loops.

Changing the code to solve a problem is an effective way to debug programs. You go to where the problem is, and you start changing parts of the code. You can change whatever you want to, but you should have a general idea of how the code works. If you don't know your code very well, this can cause even more errors. You should also remember to make a backup of your code before you change anything.

If changing the code doesn't help in solving the problem, you might want to try creating test code. Creating test code allows you to focus on the problem, making it easier to see and fix. You look at the code in your program that has the problem, and then you create a new program with similar code. You then experiment with that code, switching things around or adding code to it, looking at how it affects the operation of the code. You can also do this as a way to learn some of the more confusing aspects of the TI-Basic language.

Be Prepared For Setbacks

After working on debugging a program for a prolonged period of time, with no progress and no new ideas on how to fix the error, you stop being able to effectively debug your program.

One of the simplest remedies is to just take a break from debugging and do something else. Take a walk outside around the neighborhood or take a nap. Many times after taking a nap, you will suddenly get the answer to the problem in an epiphany. In addition, it is just a good rule to take frequent breaks from programming so that you don't get burned out so easily.

Although it may seem like debugging your program will be a monumental task requiring lots of work, it is essential that you do it. If you are to release your program to the public, you don't want users complaining that it doesn't work correctly or that it contains errors.

Another cause of feeling overwhelmed is if you are not very good at debugging. When you are just starting out, you will be able to fix the simple or obvious errors, but you will have a hard time tracking down some of the more complicated errors. The only way to get around this is by repeatedly debugging programs until you have figured out the errors for yourself. The more debugging you do, the better you become at it. It just takes practice.

Often when you are debugging a program, and it seems like you just can't find the error in it, you will stop thinking logically and start thinking irrationally. Your only desire is to get the program to work correctly, so you decide that you will do that by whatever means necessary. If you still can't figure out the problem, you might start blaming the calculator or the TI-Basic language.

While blaming the calculator or the TI-Basic language will provide you with temporary relief concerning the error in your program, you have to remember that they don't do any of the thinking. They just follow what your program says to do. You are the one that is responsible for the code that you produce.

Get Outside Help

If you have tried everything that you know to do and you are still unable to fix the problem, you should now start looking for outside help. You should ask other programmers or go to programming forums. Either one of these should be able to help you with your problem.

Asking other programmers for help is a good alternative to getting mad at yourself because you can't figure out the problem. Because you wrote the code, you may make assumptions or have biases when debugging it. You know the code so well that you can't be objective. When another programmer looks at it, though, they don't have any of those hang-ups. In addition, when you're explaining the problem to the other programmer, many times the solution will come to you. Asking the other programmer for help also benefits the other programmer because they improve their confidence debugging programs.

If you asked another programmer for help and they could not find and fix the problem, you should then go to programming forums. The advantage of programming forums is that several programmers are working together, building off of each other's ideas. This is the ideal situation because the more people looking at the code, the greater the chance that the problem will be found and fixed.

Here are some programming forums that you should go to if you ever need help with a problem:

<< Program Cleanup Overview Optimization >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/debug


Setting Up A Program
toolbar-separator.png This article is part of the coding stage of the development cycle.

At the beginning of a program, you typically setup everything that the program will use while it's running. Of course, there are lots of things that you may decide to include in your individual program setup, but the three main things that you should include are: the home screen, graph screen, and initializing variables. There are also some general, but crucial mode settings that should be taken care of.

General Settings

There are some general mode setting that you'll want to pay attention to. Most of those should be what you want, but there is always a chance that a program forgot to switch back to the standards, or that the user was playing around with the calculator.

In the mode menu, there are probably four different modes you need to worry about. These are numeric notation, decimal, real/complex mode, and screen display.

Numeric Notation

How numbers are displayed/returned: Normal, Scientific, and Engineering. Scientific will have one digit on the integer side, and Engineering will have two digits. The standard is Normal.

Decimal

In programs that use pinpoint precision numbers or require complex formulas or calculations, the number of decimals returned can greatly affect the program. Float will automatically adjust to the number of digits the calculator considers significant. Fix 1-9 will fix the calculator to display 1-9 digits, no matter what. This means that the calculator may sometimes give weird results such as 3.100000, or pi=3.

Real/Complex Mode

The default mode, Real, will give ERR:NONREAL ANS whenever a complex number is obtained as a result. If you want to use complex numbers, you should change this setting to a+bi or re^θi (the distinction between these two is only a display one).

If you're going to be using complex numbers, you should switch away from Real mode. Otherwise, it's an inessential setting. Switching to Real mode doesn't have any real (he he) purpose to it, since it doesn't provide any extra functionality - unless of course you like it when your calculator throws errors.

Screen Display

This affects the screen display. Full is probably the one of the only ones you have ever seen. Horiz displays a horizontal split-screen, with the graph on top and home screen on bottom. G-T displays a vertical split-screen, with graph on left and table on right. The standard is Full.

Home Screen

Since the home screen that your program uses is the same home screen that the rest of the calculator uses, the previous program call(s) and any other text is typically still displayed on the screen. Obviously, you don't want to be displaying text and have it interrupted by other text, so you need to clear the home screen. The ClrHome command is what you use.

When using the ClrHome command, you simply place it on a line. The whole home screen will be cleared of any text; there's no way to clear a smaller portion of the ClrHome because it takes no arguments.

:ClrHome

Graph Screen

The typical TI calculator user uses the graph screen to graph, which means they use axes, stat plots, Y= equations, and sometimes the grid. They might also like drawing things with the drawing commands or the Pen. However, while working in a game in use of the graph screen, you really do not want these functions to appear, which would completely mess up your program.

First, you need to disable all these annoying thing by the following code:

:ClrDraw     // Clears the graph screen of all its contents
:AxesOff     // Disables X and Y axis scaling view
:FnOff       // Disable Y= equations
:PlotsOff    // Disables stat plots from appearing
:GridOff     // Disables grid from appearing

After that, you setup the window dimensions to use a friendly window. This not only makes drawing much easier, but it is faster and smaller. One way to do this is shown below:

:0→Xmin:1→ΔX
:0→Ymin:1→ΔY

Initialize Variables

If you have any important variables that you use in the main program loop, you should initialize them here, so the program will be able to use them and not have a delay. This is especially important with large variables (such as lists, matrices, and strings), since initializing those variables inside the main program loop will definitely have an impact on its speed.

:{1,2,3,4→A
:[[1,2][3,4→[A]
:"1234→Str1

Putting It All Together

Putting all the parts of program setup together, here is a typical way to start a program:

PROGRAM:SETUP
:ClrHome
:ClrDraw
:AxesOff
:FnOff
:PlotsOff
:GridOff
:0→Xmin:1→ΔX
:0→Ymin:1→ΔY
:{1,2,3,4→A
:[[1,2][3,4→[A]
:"1234→Str1

Of course, you only have to include the things that you actually use. If you don't have any important variables to initialize, then simply leave that off. In the same fashion, you don't have to clear the clear the home screen if your program just runs on the graph screen.

<< Usability Overview Code Conventions >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/setup


Cleaning Up After a Program
toolbar-separator.png This article is part of the coding stage of the development cycle.

Imagine you just finished playing a round of Blackjack, and now you're back on the main screen. You enjoyed the game, but something is just not right. Not only is there text on the home screen, but there's graphics on the graph screen, and it appears that there's some leftover variables taking up a considerable amount of your precious memory. It seems that the Blackjack game forgot to clean up after itself.

Cleaning up after a program is one of the most important parts of any game. A quality game features good gameplay, but more importantly it doesn't leave the calculator in disarray afterwards so the next program that is run isn't affected by it. While program cleanup can involve whatever the game programmer wants, there are a few standard parts to it.

Deleting Large Variables

The first, and arguably most important, part of program cleanup is deleting variables. After a program finishes running, it should delete any large variables that it created during its execution. The program should only keep variables if they are used for storing important information, such as highscores or map data. You can delete a variable using the DelVar command (provided that the variable is not in the archive).

The user does not want to have their memory cluttered up with lots of variables because it makes scrolling through the memory menu that much harder. They also don't want to lose any of their memory because it prevents them from using it for any other things they want to do (such as running other programs).

Restoring the Graph Screen

After deleting large variables, the next part of program cleanup is to restore the graph screen. Besides clearing the graph screen (using the ClrDraw command), you should recall the graph database (GDB) variable that has the previous window and graph format settings stored in it. (Please note that GDBs do not contain text, graphics, or stat plots.)

You want to make sure to clear the graph screen when exiting programs because this ensures that the next program that the user runs won't have to deal with whatever text or graphics your program left behind. It also helps the user because they won't have to manually clear the graph screen themselves.

At the beginning of a game that uses the graph screen, select whichever GDB you want to use (GDB0 through GDB9) and then use the StoreGDB command to save the window and graph settings into that GDB. Now when the program is finished executing, recall that GDB with the RecallGDB command to recreate the graph screen with the previous graph and window settings that were stored in it. You should then delete the GDB.

Clearing the Home Screen

Once the graph screen is restored, the next part of program cleanup is to clear the home screen using the ClrHome command. Clearing the home screen ensures that the next program the user runs will not have to deal with whatever text the program left behind. It also helps the user, because they will not have to manually clear the home screen by pressing the CLEAR key; you have already done it for them.

Besides clearing the home screen when cleaning up, you should also remember to remove the "Done" message that shows up after a program finishes executing. This "Done" message is a clear indicator that your program just finished running (which can be bad if you are in class and your teacher is near by), and it also does not look very good.

When you display text, a number, a variable, or an expression with a display command (either Disp or Output() on the last line of the program, you can remove the command and just put argument by itself. The argument will be displayed instead of the "Done" message that is normally displayed after a program finishes executing, and it will also be stored into the Ans variable.

:ClrHome
:Disp "Hello
Remove Disp
:ClrHome:"Hello

If you do not display any text on the last line, or you do not have any particular text that you want to be shown, you can still remove the "Done" message by just putting a single quotation mark. This will have the same effect, but there will be no text and the cursor will be placed on the second line.

:ClrHome
Put a quote
:ClrHome:"

In addition to removing the "Done" message, this text also acts as a way to clear the Ans variable. For example, if you had a large variable stored in Ans (such as [A]), which subsequently would cause Ans to also be large, this text would make Ans release that excess memory back to the calculator. You could also add the Clear Entries command before the final text just for good measure.

To remove the "Done" message without moving the cursor (slightly larger):

:ClrHome
:Output(1,1,"             //no space, just a quote

List Editor Cleanup

If you used the SetUpEditor command for lists that your program uses, that also causes the list to appear in the "List Editor" the next time the user accesses it (STAT>Edit…). This probably isn't desired behavior, because it looks unprofessional, and because your program's list is likely to contain highscores and other data of that nature.

To fix this, add a SetUpEditor without any arguments to the end of your program. This will reset the List Editor to the default settings (it will show the contents of L1, L2, …, L6). This isn't perfect, since the user may have been editing his own lists there, but it's the best you can do, since TI-Basic can't find out about the user's previous settings.

If you don't want to restore L1 through L6, you can do:
:SetUpEditor L<name>
:Archive L<name>
:UnArchive L<name>

This will remove L<name> from SetUpEditor.

Putting It All Together

Putting all the parts of program cleanup together, here is a typical way to end a program:

PROGRAM:CLEANUP
:SetUpEditor
:DelVar Str1DelVar [A]
:RecallGDB 1
:DelVar GDB1
:ClrDraw
:ClrHome:"

Of course, you only have to include the things that you actually use. If you don't use any large variables, you don't have to delete them. In the same fashion, you don't have to clear the graph screen and restore the graph screen settings if your program just runs on the home screen.

Advanced Cleanup

If you have a lot of number variables that you used in your program like A, B, C, continuing through Z; you may want to consider using a hexcode to help clear all the variables rather than have a large number of DelVar statements. Although this code takes more memory and requires a subprogram, it can save a lot of typing. Lets take a look at the Delvar Hexcode. This hexcode will take a string in Ans of the name of a variable to delete, and will delete it so long as it is prefixed correctly. To start building the cleanup routine, make a new program containing just the hexcode in it. Save it as something you will remember; I called mine "ZDELVAR". Next, we need to put the code for the routine into our main program. The code looks like this:

"ABC"→Str1
For(θ,1,length(Str1)
" and "+sub(Str1,θ,1
Asm(prgmZDELVAR
End
DelVar Str1

Let's take a closer look at how it works. We store all of the variables we want do delete into String 1. Now we want to run the hexcode for each letter in our string, so we add in a for loop. The starting position will be 1, and the ending position will be however long String 1 is. We know that the hexcode takes an input in Ans, and that real variables have to be prefixed with " and " for the hexcode to work (note that this is the boolean and found in 2nd+Math). So lets take the string " and ", and then add to it the current letter we are on. Now that we have the format we need for the hexcode, run the hexcode! When we finish deleting all the variables, delete String 1. It's as simple as that! All you have to do is put which variables you want deleted into String 1!

If you wanted to delete all the strings, pictures, gdb's, or matricies you can do that too. Simply add the code for the routine again, but change the " and " to the proper prefix and change the variable names!

<< Subprograms Overview Debugging >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/cleanup


Usability (User-Friendliness)
toolbar-separator.png This article is part of the planning stage of the development cycle.

Imagine you are using a program for the first time. You have no prior knowledge about the program; someone just put the program on your calculator without giving you any instructions and now you are trying to figure out how to use it. After literally pressing all of the keys on the calculator and trying all sorts of key combinations, you give up and and delete the program.

This example isn't based off any one particular program, but it does resonate with lots of program users who have had a similar experience. What this problem really is about is poor user-friendliness — more commonly known as usability. The definition of usability is simply how easy it is for people to use a program.

While usability can take on many different forms, there are some essential things that you can do to make a program more user-friendly.

In-Program Help

Probably the easiest way to make a program user-friendly is by including some in-program help. While you ideally want your program to be so easy to use that a user can simply pick it up and figure out how to play it, not every game is so straightforward, and the average user probably needs some help.

The best place to include help in a program is as one of the options in the program's main menu. When the user comes across the menu, they will see the help option and they can select it to view the help. The help does not need to cover every minute detail about the program, but rather just explain the objective of the game and detail what keys are used for controls.

:Menu("Some Game","Option 1",1,"Option 2",2,"Help",3
...
:Lbl 3
:Disp "Game Objective
:Disp "Key = Function

Because most people do not like using help unless they have to, you should try to limit your help to one or two screens at most. At the same time, if you have an extremely complex game with all sorts of features and lots of keys are needed to operate it, then it would be appropriate to include help for all of those things. The general guideline is that the amount of help needed correlates to the size of the game.

Protect the User

The next thing you can do to make a user-friendly program is to protect the user from themselves. Often times in a program you will want to think about what could go wrong and try to either prevent it from happening or tell the user what's wrong. Preventing it from happening involves you, the programmer, programming in safety protections for the user so that they aren't even aware that something went wrong.

Say the program calls for the user to type in a number between 1-1000, and the user types in 5000. If your program just goes on with this value, it will probably crash at some point later on. Rather, it's necessary to check the value, and display an error message and ask for the number again if it's wrong. The error message does not need to be complicated or long — just enough so that you can provide some direction on what input you are expecting the user to enter.

:Disp "Enter a Number
:Input "Between 1-1000",A
:While A<1 or A>1000
:Disp "Must Be 1-1000!
:Input "Number",A
:End

Of course, just checking to see that the number is in the appropriate range is sometimes not enough. You might also want to check to see whether the user tried to enter text or a list for input. Because there is no viable way to perform those checks when dealing with a real variable, a better option would be storing the input to a string and performing the validation on it, and then converting the string to a real variable.

Include Helpful Features

Another part of making a user-friendly program is to include helpful features. Since the target audience is often in high school, a feature sure to be appreciated is a "teacher key." This is a special key that the user can use to quickly exit the program. When the teacher comes around, they then want to be able to get back to the home screen so that they don't get their calculator taken away.

This problem is quite easy to prevent with a teacher key. In every program there is a main loop that runs throughout the life of the program. You need to add a check for whatever teacher key you want at the place in the main loop where you check for user input. While you can have any key function as the teacher key, the community standard is usually MODE or DEL. (It is probably best for you to continue this so that users don't have to deal with figuring out which key is the teacher key.)

:While main loop not finished
:Display something
:Perform calculations
:Get user input
:If teacher key pressed, exit program
:End user input
:End main loop

Progress Indicators

In games that use maps, the program has to go through the list of maps and then load the appropriate one for the user to use. Depending on the size and number of maps, this can take a while. If the user doesn't know what is going on, they probably will think the program stalled or something else went wrong.

While there are a couple different ways you can cut down on the loading times for maps (see subprograms and compression), the easiest way to solve the problem is by simply telling the user what is going on and showing the user some progress. You don't have to do anything fancy (in fact, you probably shouldn't because that would just waste valuable memory), just something to help the user understand the situation.

For example, say you are randomly placing mines throughout the map (it's a Minesweeper game), you then could just display a "Placing Mines" message on the screen and have a loop for the progress indicator that matches the current map loading:

:Output(3,2,"Placing Mines
:For(X,1,20
: // fill the map with mines
:Output(4,6,5X
:End

Follow the KISS Principle

The last important point of usability is following the KISS principle. For those who haven't heard of KISS, it is an acronym which stands for Keep It Simple Stupid. The basic point of KISS is to not clutter your program with unnecessary features and useless fluff. It also entails making the program easy to figure out for those who don't have access to a readme.

It is not uncommon to see a TI-Basic math program (i.e., quadratic solver) that has a menu, about screen with scrolling credits, and includes some game in case you somehow get bored solving quadratic equations. While those things by themselves aren't bad, they are completely inappropriate in a math program. There is a certain elegance that comes with "programs that do one thing and do it well." This is known as the Unix philosophy, and should really be what every program strives for.

<< Portability Overview Program Setup >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/usability


Portability
toolbar-separator.png This article is part of the planning stage of the development cycle.

Portability is the ability to run a program on more than one calculator, with little to no changes made to the program — you can literally transfer the program to a calculator, and then start using it. This ability is important because all of the TI-83 series calculators are very similar in TI-Basic support and calculator hardware, so people expect when they find a TI-83 series program it will work on their calculator.

There are five primary things that you need to consider when making a program portable:

  • Making sure not to use assembly programs
  • Making sure not to use new commands (see compatibility)
  • Making sure not to use undocumented functionality (see compatibility)
  • Making sure not to use extra characters
  • The calculator's memory and speed

Assembly Programs

Although assembly programs allow you to make your programs look nice, and to use functionality that isn't normally possible or viable in TI-Basic (such as creating parallax scrolling using xLIB), they are not portable because they need to be compiled to work on each calculator.

This is because assembly programs are programmed in the calculator's own machine language, and use memory addresses that are specific to a particular calculator model. This means, for instance, that a TI-83 assembly library that inverts the graph screen will not work on any of the new TI-83 series calculators.

The TI-83 also uses a different format to run assembly programs than the other TI-83 series calculators: Send(9prgmNAME). This use of the Send( command does not work on any of the other calculators, and in fact will result in a ERR:SYNTAX error. Instead, the rest of the TI-83 series calculators provide three commands — Asm(, AsmPrgm, and AsmComp( — for running and compiling shell-independent assembly programs.

Two additional commands for running assembly programs have been added to the TI-84+ and TI-84+SE calculators: OpenLib( and ExecLib. These can be used for running routines from Flash application libraries that have been specifically written for use with them; the only application so far is usb8x, which is used for interfacing with the USB port.

Apart from use of these last two commands, however, most assembly programs ought to be compatible between the TI-83+/SE and TI-84+/SE

New Commands

With each release of a TI-83 series calculator, TI has added new commands to the calculator. The TI-83+ calculator introduced Archive, UnArchive, and GarbageCollect, which are designed to work with the Flash memory available on the calculator. This is in addition to the assembly commands that were mentioned earlier.

The TI-84+ and TI-84+SE calculators introduced several new time and date commands, some of which use the new built-in clock, while others are used for formatting times and dates; and the aforementioned OpenLib( and ExecLib for running routines from Flash application libraries. The new OS (2.30 or later) also includes some additional commands for statistics: Manual-Fit, invT(, LinRegTInt, and χ²GOF-Test(.

Undocumented Functionality

Along with documented changes, different calculators and OS versions have sume undocumented differences. These are given below grouped by the first calculators they occur on:

TI-83+ or higher:

  • Large font on the graph screen — Use the syntax Text(-1, row, column, text) to display text in the large font instead of the typical small font associated with the graph screen.
  • Fast circle drawing — If you put a complex list, such as {i}, as the fourth argument of Circle(, the circle is displayed using its symmetries to only do 1/8 of the trigonometric calculations; this cuts the display time down to only about 30%.

OS version 1.15 or higher:

  • The % Command — The % symbol is an undocumented command that is a useful shortcut for percents — it divides by 100, so it will convert numbers to percentages. For example, 50% will become 50/100 or 1/2, which is just what 50% should be.
  • The sub( Command — If only one argument is given, and it contains an expression that evaluates to a real or complex number or list of numbers, the argument will be divided by 100. A simpler version of the % command above.

TI-84+ and TI-84+ SE:

  • Using the Text( command for small text will sometimes erase the row of pixels below the text (usually not noticeable, when text is displayed on an already-white background). See the command itself for more information.

Extra Characters

At three points in TI-83 series history, TI allowed more characters to be used in TI-Basic. However, this means that if you use a new character, it will not work on older calculator models.

  • First group: This includes the lowercase letters, Greek letters, and international characters. These characters will work with all calculators starting with the TI-83+, but there may be some issues with computer programs such as the TI Program Editor.
  • Second group: The ~ @ # $ & `; \ | _ % characters were introduced only with OS version 1.15 (and will work on all higher versions).
  • Third group: The … ∠ ß x T ← → ↑ ↓ x ∫ √ EFh_LUpBlk.gif F0h_LDnBlk.gif 7Fh_LinvEQ.gif charactes and subscripts 0 through 10 were introduced only with OS version 1.16 (and will work on all higher versions).

Calculator Memory & Speed

The TI-83 is the oldest TI-83 series calculator, and it only has 27KB of RAM and a 6MHz processor. A program cannot really even take up the whole 27KB of RAM, since there is the in-game use while running the program. In addition, the 6MHz processor is slower than any of the other calculator processors, so if a game is only marginally playable on the TI-83+SE (with its much speedier 15MHz processor), then there is no way it would even be playable on the TI-83.

This primarily affects large, complex games (like the RPG's made by Kevin Ouellet, among others), but can also affect games that need a lot of speed to be fun. For example, if you have a Mario-like game where you need to keep track of and display multiple enemies on the screen, this can be quite time-consuming on the TI-83. In fact, the game would probably slow to a crawl, and you would spend most of your time waiting for things to load.

This problem doesn't only plague the TI-83, but also the TI-83+. Because the TI-83+ only has 184KB of memory (24KB RAM and 160KB Flash), each of the aforementioned RPG's by Kevin Ouellet would literally take up all of the available memory on the calculator: Metroid II, for instance, takes up over 123KB in Flash, and you need to have several of the almost fifty programs unarchived in order to actually play the game.

The TI-83+ also only has an 8MHz processor (which is just marginally faster than the TI-83's 6MHz processor), while the TI-83+SE and TI-84+SE each have a 15MHz processor. So, if a game is specifically tailored to run on those two calculators (meaning that the speed of the game is just fast enough), there is no viable way that the TI-83+ would be able to run the game at a sufficient speed (even taking into account optimization).

Thoughts to Consider

There are some additional ways that you can avoid portability problems:

  • Use SetUpEditor instead of UnArchive for a list — this is better, and doesn't lose compatibility with the TI-83.
  • If possible, replace all lowercase letters from your program with lowercase stat variables from the VARS>Statistics… menu, or just use uppercase letters everywhere.
  • Instead of using dayOfWk(, use the day of week routine which uses the dbd( command instead.
  • Place all of the calculator specific code into subprograms that the main program calls: one program is your game functions that work on the respective calculators and the other program is the primary all-calculator code for the program.
<< Planning Programs Overview Usability >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/portability


Optimization
toolbar-separator.png This article is part of the revising stage of the development cycle.

A dictionary would define optimization as the process of making something better. In the field of TI calculator programming, it refers to improving code to use less memory, whether as program size or in the size of variables used, or to run faster. It should be your goal, in virtually all cases, to make your programs as optimized as possible.

Line-by-Line Optimization

Optimization techniques fall naturally into two classes. The first, which we'll call "line-by-line optimization", refers to ways of rewriting a line of code, or several lines, so that it does basically the same thing, but is smaller or faster. Typically, each such optimization doesn't have a huge effect. But since many lines can be improved this way, these optimizations add up over the entire program to produce a smaller and faster result.

Read the basic techniques of line-by-line optimization. Then, consult the following pages to see techniques for specific topics:

Alternatively, you can read the optimization walkthrough for a look at applying the optimizations in a real program.

Algorithmic Optimization

An algorithm refers to your method of solving a problem. Algorithmic optimization, then, relies on choosing the best method to solve a particular problem. Unlike line-by-line optimization, even a single optimization of this type can have drastic results — but it also requires critical thinking and a case-by-case approach.

Most programmers, after thinking about the methods they will use for a while, never spend much time on this kind of optimization. It becomes important when you're pushed in a corner: your program has become so large that it doesn't have enough memory to run, or takes half a minute to load each screen.

Identify the bottleneck in your program — what is it that takes up all the memory, or that the program spends so much time doing? Then consider several fundamentally different approaches to solving that particular problem (be it the problem of storing a large matrix or of displaying a tilemap). Write routines implementing each approach, fully optimize all of them, and compare the results. And make sure that you're not missing an approach too radical to think of. Virtually all of the techniques you find in this guide have been discovered by frustrated programmers doing exactly this kind of thinking.

Read the algorithmic optimization tutorial for a demonstration of the process of algorithmic optimization in a real programming situation.

<< Debugging Overview Code Timings >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize


Code Timings
toolbar-separator.png This article is part of the revising stage of the development cycle.

This page documents the speed of certain commands in TI-83 Basic. Although the times given here will vary from model to model and even from calculator to calculator (due to battery levels, free memory, and other factors), one thing that does not change is the relative speed of the commands. So, if you come here to see if a For( loop is faster than a While loop, the information will be useful on any calculator.

Elsewhere on this site, you might see assertions like "foo() is faster than bar()" without any reason or proof. The information on this page is the reason and proof behind them.

Testing Format

In order to be able to compare speed results between commands, there needs to be a common format that is used for all of the tests. However, there are actually two different formats that you can use depending on which TI-83 based calculator you have.

The first format is for those with a TI-83, TI-83+, or TI-83+SE, and it is just a simple For( loop that is executed a set number of times over the command:

:For(n,1,[number]
: <command(s) to be tested>
:End

You measure the time by getting out a stopwatch, and trying to estimate the number of times the run indicator moved. The run indicator is the little, one pixel wide bar in the upper right corner of the calculator that moves when you run a program. Each completed run indicator you count as eight, and then any leftover pixels you simply add to the total.

Of course, because the run indicator moves quite fast, this testing format can be plagued by human error. If you have any second guessing or are unsure if a timing was correct, you should run the test again. You can then take the average of the two times as your result.

The second format is for those with a TI-84+ or TI-84+SE, and it involves using the built-in startTmr and checkTmr( commands. You first store startTmr to a variable (usually a real variable), and then run your command inside of a For( loop. You then check the time with the checkTmr( command using the variable from before that startTmr was stored to.

Here is a basic template to use:

:startTmr→T
:For(n,1,[number]
: <command(s) to be tested>
:End
:checkTmr(T)/[number]

The n variable can be found by pressing [2ND][0][LOG]. This variable has a static memory address, so it won't affect the accuracy of the timings.

Making [number] higher increases accuracy, but takes longer. Also, make sure not to modify the variables n or T inside of the For( loop.

While this format eliminates human error from counting, it's prone to its own faults. A major one is that startTmr and checkTmr( always return whole numbers, but time is continuous. Depending on how close the start and end of the loop were to a clock tick, the number of seconds may be off by up to one second in either direction. This error is greatly reduced by conducting more trials: an error of ±1 second is reduced to ±0.001s per trial by running 1000 trials.

If there is a need to use one or more variables during a test, you should initialize the variables to a known value before running the test. You can do this either on the home screen or before the format code (in which case, you should also put a Pause to separate the variable initialization from the code test). If the code being tested contains and If statement on the fist line, it is highly advisable to add the closing parenthesis to the For( loop.

Contributing your own Tests

Feel free to experiment with code timings, and to put your results up on this page. However, be sure to list the calculator model and the OS version (found in the About menu) that you used! Unless stated otherwise, all tests on this page were done with a TI-83+ and OS version 1.19.

That's it for details and explanations. Now come the actual timings!

Program Main Code

If statements

This very first section is a difficult one to approach, because the nature of our testing method affects it. It turns out that the For( command, when it doesn't have a closing parenthesis after it, will slow down If statements with a false condition inside the loop. This doesn't affect the speed of any other commands (except IS>( and DS<( which are rarely used), nor does this effect occur with a true condition, nor with If-Then-End blocks (just with a single If and a command following it). These two pieces of code will be affected, for instance (the second will be much faster):

:For(I,1,100
:If 0:
:End
:For(I,1,100)
:If 0:
:End

The following table summarizes all of these effects. It would have been too cumbersome to maintain the same format as elsewhere, so the number is simply the total number of pixels.

Conditional type For(A,0,2000 For(A,0,2000)
If 0: 1520 79
If 1: 79 82
If 0:Then:End 80 83
If 1:Then:End 89 91

Conclusion: The ending parenthesis situation, when it is applicable, is a major factor, slowing the statement down nearly 20 times. For this reason, I suggest that if there's any chance at all the condition is false (which is always the case, or else why are you testing for it in the first place?) to leave on the parenthesis on the For( loop. Of course, this doesn't affect If-Then-End commands.

It was long held, because of a misunderstanding of this effect, that If commands were slower than If-Then-End (prior versions of this page were not entirely innocent, either). As you can see, this is not the case, as long as you are aware of the effect shown above. Though there are slight differences in the timings, they are so small that you can ignore them.

Relational Operators

In all programs, there is a lot of chances that you will see relational operators used to determine what to do. But will each of them take the exact same time to work?
Format Bars Pixels Total
= 10 4 84
10 5 85
> 10 5 85
10 5 85
< 10 5 85
10 6 86
and 10 6 86
or 10 6 86
not( 8 6 70
xor 10 5 85

Conclusion: If you can reverse your operations, then do it to save some time.

int( vs. iPart(

As you may know, int( and iPart( have the same use, for positive numbers at least.. In programs where you store more than one variable in 1 number, you normally use int( or iPart(, but which is the best one to use?

Format Bars Pixels Total
iPart(1 10 1 81
iPart(1.643759 10 1 81
int(1 8 7 71
int(1.643759 10 2 82

Conclusion: Unless there are 6 or more decimals, you should consider using int( because of it's speed, but with several decimals, iPart( stays the same so it goes faster.

The getKey Function

I hope you all know the getKey function, it is probably the most used in games and custom menus. It takes time, but we still don't know if it is fast…

Format Bars Pixels Total
Getkey 7 5 61
Getkey→B 11 0 88

Conclusion: getKey is pretty fast, but storing to the variable takes a lot of time. So, if you don't need to have the value of the key pressed, don't store it and use the special variable Ans instead.

For(, Repeat and While Loops

There are many types of loops that you should know already: For(, Repeat and While loop. But if we have the choice, which one is faster?

:For(A,0,2000
:While 0 :End
:End

12 bars +2 pixels (98 pixels)

Also see that with For(A,B,C loops implementation, you can do an If statement:

If B≤C, then C+1→C (at the end)
If B>C, store B into A

:For(A,0,2000
:For(B,1,0
:End
:End

12 bars (96 pixels)
:For(A,0,2000
:Repeat 1
:End
:End

13 bars +2 pixels (106 pixels)

Conclusion: There is one loop that is best. Use the right loop for the task you need to do.

:For(A,0,2000
:End

4 bars +4 pixels (36 pixels)
:Delvar A
:While A≤2000
:A+1→A ;No use of Ans because there should be other code in the loop that would mess up with Ans...
:End

23 bars (184 pixels)
:Delvar A
:Repeat A>2000
:A+1→A ;No use of Ans because there should be other code in the loop that would mess up with Ans...
:End

22 bars +7 pixels (183 pixels)

Conclusion: For the same use, please use a For( loop…

Graphing Code

The pxl-Test( Function

Many TI-BASIC programmers reported issues of when pxl-Test( is a conditional, it takes up to 40% more time.

Format Bars Pixels Total
pxl-Test(15,15 ;pixel turned off 12 1 97
pxl-Test(15,15 ;pixel turned on 12 1 97
If pxl-Test(15,15: Then: (empty line): End ;pixel turned on 20 0 160
If pxl-Test(15,15: Then: (empty line): End ;pixel turned off 18 6 150
pxl-Test(15,15: Then: (empty line): End ;pixel turned on 24 2 194
pxl-Test(15,15: Then: (empty line): End ;pixel turned off 22 7 183

Conclusion: For my calculator, at least, it didn't give me the errors reported by others. So don't use pxl-Test(:If Ans, but If pxl-Test(, it goes faster and takes a byte less. Also, it doesn't matter whether pixel is on or off.

Pixel and Point Modifying

The objective in having games on the 83+ is mostly because it has good graphics that are entertaining. This is why we need to open or close pixels in order to draw. I made my test with a window size of: Xmin=0, Ymin=-62, Ymax=0, Xmax=94

Format Bars Pixels Total
Pt-On(15,-15 14 0 112
Pt-On(15,-15,2 20 1 161
Pt-On(15,-15,3 18 2 146
Pt-Off(15,-15 14 0 112
Pt-Off(15,-15,2 20 1 161
Pt-Off(15,-15,3 18 2 146

Conclusion: So like we see, Pt-On/Off is the same time of execution.

Format Bars Pixels Total
Pt-Change(15,-15 14 0 112
Pxl-On(15,15 9 4 76
Pxl-Off(15,15 9 4 76
Pxl-Change(15,15 9 4 76
Line(15,-15,16,-15 16 2 130
Line(15,-15,30,-15 32 6 262
Line(15,-15,30,-15,0 34 6 178
Horizontal -15 82 5 661
Vertical 15 60 3 483

Conclusion: Line(, Horizontal and Vertical are all slow, but they can save bytes. If there are under 4 or 5 pixels to turn on, Pxl-On( works much faster than any of them. However, if you have a lot of pixels to turn on/off, it is much better to use them than the Pxl-/Pt- commands. Also, Pt-Change( is the same speed wise as Pt-On/Off.

Text( vs. Output( vs. Disp(

In all your programs, there is probably something that displays text on the screen. There are many ways to do so, so I will look at them to see which one is faster. The codes will be displaying the same string, "I DIE!", so that I can give you valuable timings. In order to find the timing of display, ClrHome is after all of the commands.
Format Bars Pixels Total
Text(-1,16,12,"I DIE! 54 4 436
Text(16,12,"I DIE! 41 1 329
Output(3,2,"I DIE! 37 6 302
Disp "I DIE! 51 2 410

Conclusion: For immobile text, if you need to be big, you should use Output(, but if you need it into graph screen, then think about the time it takes…

Format Bars Pixels Total
Output(3,2,A 16 6 134
Text(-1,16,12,A 36 7 295
Text(16,12,A 27 0 216

Conclusion: For variables' values, same thing applies.

Optimizing your Code

Parentheses and Quotes

Normally, you shouldn't close parentheses and quotation marks to save a byte. I will test if it goes faster.

Format Bars Pixels Total
Output(3,2,"I DIE! 20 6 166
Output(3,2,"I DIE!" 20 6 166
(5+6)→B 13 6 110
(5+6→B 13 5 109
5+6→B 13 2 106

Conclusion: The only reason you need to get out the quotations marks are because you save 1 byte, you don't get faster. Also, taking off closing parenthesis goes faster. However, it is better if you can get rid of the parentheses entirely.

Multiplication, Division and Addition

Most TI-BASIC programmers tell you not to put the multiplying * sign, but do they know if it goes faster?
Format Bars Pixels Total
A*B 13 4 108
AB 13 2 106

Conclusion: If you multiply, don't put the * sign.

Format Bars Pixels Total
If AB: Then: (empty line): End ;Condition true 20 5 165
If A and B: Then: (empty line): End ;Condition true 20 5 165
If AB: Then: (empty line): End ;Condition false 18 7 151
If A and B: Then: (empty line): End ;Condition false 19 2 154

Then you could possibly use the AB format because there is 1 byte less and no speed loss and if the condition is mostly false, AB goes faster…

Format Bars Pixels Total
If C+B: Then: (empty line): End ;Condition true 20 6 166
If C or B: Then: (empty line): End ;Condition true 20 6 166
If C+B: Then: (empty line): End ;Condition false 19 3 155
If C or B: Then: (empty line): End ;Condition false 19 7 159

Same as for the last tests, but you don't save any space.

Format Bars Pixels Total
If A(C+B: Then: (empty line): End ;Condition true 25 4 204
If A and (C or B: Then: (empty line): End ;Condition true 25 1 201
If A(C+B: Then: (empty line): End ;Condition false 23 4 188
If A and (C or B: Then: (empty line): End ;Condition false 23 7 191

Conclusion: So as we can see, in multiple conditions, where it should be true a lot of time, you should use the and and or operators instead of multiplication and addition.

Format Bars Pixels Total
A/B 20 6 166
AB^-1 28 2 226
The following timings were taken on a TI-84+ SE with OS version 2.40
Format Bars Pixels Total
1/B, when B=1 15 0 120
B^-1, when B=1 14 1 113
1/B, when B=pi 20 2 162
B^-1, when B=pi 19 2 154

Conclusion: When dividing two numbers, don't use the ^-1 operation. It goes really slow! But if you're only taking an inverse, use the ^-1 operation instead of dividing from 1.

Variables

Some variables types are supposedly faster than others. Let's find out!

Format:
1→_
ClockOn
startTmr→C
For(T,1,E5
_
End
Disp checktmr(C)/E5

Variable Time
N 0.00275
Xmin 0.00275
N 0.0321
Ans 0.0321
[A](1,1 0.00328
L1(1 0.00385
Str1 0.00385
Ans(1 0.00482

Conclusion: Use Finance Vars! Although, it is your choice: a 2 byte, really fast variable (i.e., the finance variables) or a 1 byte, slow variable (i.e., the real variables). Also, just because Ans wasn't any faster, doesn't mean you shouldn't use it! It can make your code a lot smaller, and may be faster in some situations.

Recalling Lists

As you know, lists are arrays of variables, that you can modify specifically, one by one. You can use pre-defined lists, such as ∟1, ∟2, …, ∟6, and user-defined lists, LXXXXX where X represents any letter or number or nothing at all (except for the first character). It takes time recalling an element, but how much?

Format Bars Pixels Total
\L1\ 13 6 110
\L1\(1 15 0 120
\L\A 15 3 123
\L\A(1 16 6 134
\L\AA 15 5 125
\L\AAA 15 4 124
\L\AAAA 16 2 130
\L\AAAAA 16 2 130
A 9 6 78

Conclusion: If you can, use pre-defined lists as temporary buffer, but not for long-term storage, it is so easy to get it modified in a math class. And if you can, use real variables instead of lists if you have very few elements and that the data storage is not long-term.

Imaginary vs. Decimals

If you have looked in some tutorials, they talk about having many different variables held in one variable, by using either imaginary numbers in rectangular form (A+Bi), or decimal points (XX.YYMMDDNNIIJJ). It saves space for keeping track of saved games, and sometimes time if you use it correctly. But which ways are the fastest?

Format Bars Pixels Total
real(4+4i)+imag(4+4i 23 4 188
real(4+4i 14 6 112
imag(4+4i 14 6 112
int(4.4)+10fPart(4.4 15 2 116
int(4.4 8 6 70
10fPart(4.4 11 1 89

Conclusion: If you can, try not to use imaginary rectangles, they are slower than their int( and fPart( equivalent and they store the exact same amount of data. Besides that, a complex variable is twice as big as a real variable, and if you use one in a list it will make even the real elements twice as big.

Calculating powers of 10

The calculator has at least three ways to calculate some power of 10: using the small E command (limited to integer powers), using the 10^( command, and typing out 10^. How do these compare?

Format Bars Pixels Total
E1 6 6 54
10^1 9 0 72
10^(1 12 4 100
E99 6 7 55
10^99 50 6 406
10^(99 12 6 102

Conclusion: The E command wins out by far, but it's limited, so you can't always use it. In those cases, typing out 10^ is slightly faster than the 10^( for small arguments (the breaking-even point seems to be around 10^9), but is a lot slower for large arguments. Of course, there's also the size to consider, so the command seems to be a pretty safe bet.

IS>( vs. If command

This is what happened when I compared IS>( to If conditionals:

Format Bars Pixels Total
IS>(B,10):Disp 24 2 194
If B>10:B+1→B:Disp 34 3 275

Conclusion: IS>( works faster, but its flaws might not make it very useful.

Alternate methods

getKey routines

These are two different methods of moving an X on the homescreen.
Darkstone Knight's alternate method. (123 bytes, 12 bars, 7 pixels, 103 pixels total)

:ClrHome
:1.01→A
:For(D,0,200)
:getKey
:If Ans
:Output(iPart(A),(smallcapitalE)2fPart(A)," /one space/
:A+(Ans=34 and A<8)-(Ans=25 and A≥2)+sub((Ans=26 and fPart(A)<.16)-(Ans=24 and fPart(A)>sub(1→A
:Output(iPart(A),(smallcapitalE)2fPart(A),"X
:End

and the original method using piecewise expressions. (109 bytes, 13 bars, 104 pixels total)
:ClrHome
:1→A
:1→B
:For(D,0,200)
:getKey→C
:If C
:Output(A,B," /one space/
:A+(C=34 and A<8)-(C=25 and A>1→A
:B+(C=26 and B<16)-(C=24 and B>1→B
:Output(A,B,"X
End

So which one you use depends on your value of 1/200th of a pixel per iteration vs. 14 bytes of size.

<< Optimization Overview Writing Program Documentation >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/timings


Releasing Your Program
toolbar-separator.png This article is part of the releasing stage of the development cycle.

Many programming guides give you excellent advice on programming, but stop at the point when the program is finished, tested, and optimized. After all, most people can manage to release a program somewhere, one way or another. But in reality, an inexperienced programmer may well release his work quietly and in an unassuming form, which people will simply glance over without stopping. This tutorial will tell you how to avoid this, and make your program get all the attention it deserves.

Where to Release

First, it's important to know where to go to upload your program to the Internet. Although you might want to create your own website and release all your games there, that alone will not get your program noticed. Sure, having your own site might get you some publicity, but the best way to get your game noticed is by releasing it at one (or all!) of the large program archives.

Of these, ticalc.org is by far the largest (and most popular), but it's also likely you'll spend longer waiting for your program to be put up there. With CalcGames, and United-TI, you only have to wait a day or two. With TI-Basic Devloper, you only have to wait a few minutes, or you could do it yourself.

What to Release

There's more you'll want to submit than just the program itself. Here are the elements you'll want to put together — some of these are called optional by the file archive websites, but they are mandatory if you want the program to be successful.

The program itself (obviously)

If you were programming on the calculator, you'll need to transfer the program to your computer to submit it. You'll need a calculator-to-computer cable, and software such as TI-Connect. If you don't know where to get these, or have problems using them, see linking.

Now, you have one or more files from your calculator on the computer. If there's only one, you're good to go. If there are several files involved, you should consider combining them in a group file (usually .83g or .8xg). Or keep them like they are, but then make sure to mention what each file is for, in the readme.

Although, if you don't want to worry about having to ungroup, or group the files, another option for monochrome calculators is Basic Builder. Basic Builder packages your programs, in an app. More information, is given at this page.

The readme

A critical step in submitting a program. Make sure to read our tutorial on writing a readme if you've never done it before (and possibly even if you have). Usually, longer is better than shorter (it's worse if someone doesn't understand how your program works, than if they have what they already know explained to them again) — unless it's a five-act play, in which you might consider removing the nonessentials. Generally, the longer and better your program, the longer your readme can be; you don't need any more than the minimum for, say, a quadratic solver. For a huge program, a 2-4 page plain text file is appropriate.

Also, please don't make the readmes in Microsoft Word 7 file format! A .txt file is sufficient, and in fact recommended. However, if you're just itching to put screenshots, pictures, and format your whole paragraph accordingly, a .pdf file would be a good idea. PDF files can be read by most computers automatically, but if not, Adobe reader, is free. It might be a good idea, to put a file with a link to an adobe download station. Most likely http://get.adobe.com/reader/ will be the link to get adobe reader. You might also want to mention that it's free. Make sure you have that .txt file that gives the information on where to find adobe.

The screenshot

All four websites listed above let you add a still or animated screenshot of your program. This is very easy to do — see the making a screenshot page — and goes a long way toward making your program look good (if it actually is good). An attractive screenshot will encourage visitors to download your program more than the most flowery prose. Show your program at its most impressive here.

Getting a screenshot is easy, open TI Connect, in 1.7 and 1.6, it should look like a camera. Click it.

The title

The title will tell visitors what your program is all about. One common mistake is making the title the same as the 8-character name of the program. Don't do this — the title is the first thing people will see, and you want to make it clear. Of course, if the program is called prgmTETRIS it's okay to call it Tetris (though Grayscale Tetris, if that's the case, could be even better). But if the program is called prgmQUADSOLV, please make the title Quadratic Solver instead!

The description

Don't forget this! It should have three parts:

  • What the program is about. "Solves all quadratic equations over the complex numbers."
  • The program's best qualities. "A grayscale interface at the low size of 13 bytes!"
  • Any requirements. "Requires xLIB, Omnicalc, Symbolic, and DAWG to work correctly. Also, create and unarchive GDB7."

The first two parts are positive; the third is negative, but necessary (imagine if your program crashes without warning if GDB7 is not created. 99% of your users will be lost, even if this is explained in the readme, and write negative reviews). You want to make this section as short as possible, and the best way to do this is to avoid the requirements in the first place. Even if you're game is in the "games for xLib" category, the one who is looking for a game might not see this, and not download, or install xlib.

Putting this together

The program and the readme should be combined in a .zip archive, this is a community-wide standard. The file upload form (this is different for all websites, but contains the same basic information to be entered) should have fields where you can submit everything else. You might also consider adding the screenshot to the .zip archive, in addition to its normal location.

Here are the links to the file upload forms of all the websites mentioned on this page.

Note: You need to create an account at the respective website before you can upload files there.

Marketing

Marketing your program can start as early as when you first get the idea for your program, although many people won't take you seriously until you have at least a basic engine to show for your efforts. Other good points at which to advertise the program include a beta-testing period before you release it to the masses, and of course when it's finally released. For more marketing tips, see our marketing tutorial.

<< Marketing Overview Creating New Program Versions >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/releasing-your-program


Algorithmic Optimization

This page is pretty good describing the process of finding better algorithms.

http://tibasicdev.wikidot.com/algorithmic-optimization

Optimization

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pages:algorithmic-optimization


Optimization: Conditionals

Use If conditionals when you only want to execute the one command on the next line.

:If A=1
:Then
:C+2→C
:End

can be

:If A=1
:C+2→C

Because conditionals are generally slow, you should replace them with piecewise expressions if you are just changing a variable. You take the variable and add or subtract the expression, multiplying it by the value that you are adding to the variable. Using piecewise expressions can sometimes be slower than If conditionals to avoid storing zero into the variable if the expression is false.

:If A=3
:B+2→B

can be

:B+2(A=3→B

You don't need to put the value in front of the expression when it is one.

:B+1(A=2→B

can be

:B+(A=2→B

You can take piecewise expressions a step further by combining multiple If conditionals that deal with the same variable and put them into one piecewise expression.

:If A=3
:B+5→B
:If A=6
:B-3→B

can be

:B+5(A=3)-3(A=6→B

If you are adding and subtracting the same value from the variable in the piecewise expression, you can factor the common value from each expression. This works best when you are adding and subtracting a big number.

:B+11(A=1)-11(A=2→B

can be

:B+11((A=1)-(A=2→B

You can sometimes reorder a list of If conditionals so that the last possible outcome doesn't even need an If conditional. This mainly works when the program is going to do a certain action and there are no other alternative actions that can occur.

:If not(A
:Goto A
:If A>0
:Goto B
:If A<0
:Goto C

can be

:If A<0
:Goto C
:If A
:Goto B
:Goto A

If-Then-End conditionals should be used when you want to execute multiple commands.

:If A=1
:C+1→C
:If A=1
:D+1→D

can be

:If A=1
:Then
:C+1→C
:D+1→D
:End

If you have two or more If conditionals that have a common expression, you should take the common expression out and make it into an If-Then-End conditional and nest the If conditionals inside it.

:If A=1 and B=1
:C+2→C
:If A=1 and B=2
:D+1→D

can be

:If A=1
:Then
:C+2(B=1→C
:D+(B=2→D
:End

If you are displaying lots of text based on If conditionals, you should put the text together and then just use the sub command to get the appropriate part of the text. This will display the text if none of the conditions are true, so this may not always be desired.

:If A=3
:Disp "Hello
:If A=4
:Disp "World

can be

:Disp sub("HelloWorld",1+5(A=4),5

The If-Then-Else-End conditionals should be used if you want to execute multiple commands when an expression is true or false. Instead of putting two If-Then-End conditionals that have math opposite expressions, If-Then-Else-End conditionals are faster because you don't need to do two checks; only one of the conditionals can be true at one time.

:If B
:"Hello→Str1
:If not(B
:"Goodbye→Str1

can be

:If B
:Then
:"Hello→Str1
:Else
:"Goodbye→Str1
:End

When using an If-Then-Else conditional and only one command is executed if the expression is true or false, use an If conditional between the two commands instead. You might also have to change the order of the commands, depending upon the commands.

:If B
:Then
:"Hello→Str1
:Else
:"Goodbye→Str1
:End

can be

:"Goodbye→Str1
:If B
:"Hello→Str1

When a line is either drawn or erased depending on a condition, you can put that condition as the optional fifth argument for the Line command.

:If B:Then
:Line(1,2,3,4
:Else
:Line(1,2,3,4,0
:End

can be

:Line(1,2,3,4,B

When you have a If-Then or If-Then-Else conditional that has a Goto command as one of the nested commands, you can sometimes remove the conditional and replace it with multiple If conditionals. Doing this prevents a memory leak from happening.

:If A
:Then
:Disp "Hello
:Goto A
:Else
:Disp "Goodbye
:B+2→B
:End

can be

:If A
:Disp "Hello
:If A
:Goto A
:Disp "Goodbye
:B+2→B

If you have If:Then:End statements with an "End" at the end of the program, the End can be removed.

:If randInt(0,1
:Then
:Disp "Heads
:Else
:Disp "Tails

However, if the last line returns a value, it will show up on the home screen after the program ends.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-conditions


Optimization: Deleting Variables

Instead of setting number variables to zero (to delete them), use the DelVar command. DelVar works with all of the variables, and the calculator automatically sets the variable to zero the next time it's used. However, DelVar is also slightly - so for repeated resetting, it is often faster store 0 to the variable.

:0→A
can be
:DelVar A

The DelVar command doesn't need a line break or colon following the variable name. This allows you to make chains of variables.

:DelVar A
:DelVar B
can be
:DelVar ADelVar B

Besides making chains of variables, the DelVar command also allows you to take the command from the next line and put it immediately after the last DelVar command.

:DelVar A
:Disp "Hello
can be
:DelVar ADisp "Hello

The only exception is with the Lbl command. Don't put the Lbl command immediately after a DelVar with this optimization, or else the label will be ignored. For instance, the following code exits with ERR:LABEL:

:DelVar ALbl 0
:Goto 0

Even though the ClrList command exists for clearing lists, DelVar should be used instead.

:ClrList L1
can be
:DelVar L1

There is a drawback to using Delvar for Lists. If you use Delvar L1 instead of ClrList L1, L1 will disappear from the list editor. This can easily be remedied outside of the program, but inexperienced calculator users who execute your program and then need to view the list that was used by your program may not know how to do this.
Furthermore, ClrList L1 is 1 byte smaller than Delvar L1.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-deleting


Optimization: Exiting Programs

Although the Return and Stop commands can both be used for exiting programs, Return should be used instead of Stop. While Return stops only the current program and allows the parent program to continue running, Stop causes all of the programs to stop and then returns the user to the homescreen (unless called from an Assembly program).

:ClrHome
:Disp "Hello
:Stop
can be
:ClrHome
:Disp "Hello
:Return

You don't have to use Return or Stop if you can organize the program so that it just naturally quits. If the calculator reaches the end of a program, it will automatically stop executing.

:ClrHome
:Disp "Hello
:Return
can be
:ClrHome
:Disp "Hello

When you have a display command that displays text as the last line of the program, you can remove the command and just put the text. This text will be displayed instead of the "Done" message that is normally displayed after a program finishes executing.

:ClrHome
:Disp "Hello
can be
:ClrHome:"Hello

Even though you don't display any text as the last command, you may still want to get rid of the "Done" message. You can do this by putting a single double-quote as the last line of the program.

:ClrHome
can be
:ClrHome:"

If you modify the Ans variable on the last line of the program, Ans's new value will be displayed instead of the "Done" message.

:ClrHome
:For(A,1,5
:B+A→B
:End
can be
:ClrHome
:For(A,1,5
:B+A→B
:End
:B

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-exiting


Optimization: Logic and Relational Operators

Because the calculator treats every nonzero value as true and zero as false, you don't need to compare if a variable's value is nonzero. Instead, you can just put the variable by itself.

:If C≠0
can be
:If C

Instead of comparing a variable to zero, use the not( logical operator. Because not( returns the opposite value of the variable, true will become false and false will become true.

:While A=0
can be
:While not(A

When making expressions that combine the and and or operators where the and operator comes first, you don't need to include parentheses around the and operator. The and operator has a higher precedence than or, so it is evaluated first. This can become complicated with complex expressions, so you might want to leave some of the parentheses for clarity.

:If (A=1 and B=2) or (A=2 and B=1)
can be
:If A=1 and B=2 or A=2 and B=1

If you are comparing two unary expressions (expressions with no comparison operator) with the and operator, you don't need the and operator. For and to be true, both values must be nonzero. So, multiplying them will produce the same effect because if either one of the values is zero, the product of both values will also be zero.

:If A and B
can be
:If AB

A similar technique can be applied to expressions with comparison operators, except some restrictions are required.
With unary expressions, to test If A and B is true you multiply them. With equations, you can multiply the left sides of each together and you can do the same for the right sides. However, a value being 0 could return a different result than anticipated, so it is best to use this technique when the values are not 0.

:If A=B and C=D
can be
:If AC=BD

As and is similar to multiplying, the or operator is similar to addition. Adding two values together yields a non-zero result if one of the conditions is true. When you are comparing equations using the or operator, you can add the two together (This is not used for unary expressions because the plus symbol and or symbols are both one-byte tokens). For this the only restriction is that all values must have the same sign (or be 0), or you can circumvent this by using abs(. This is necessary because if two variables have the same value except one is negative, this expression could return false.

:If A=B or C=D
can be
:If A+C=B+D

The most unused logical operator is xor (exclusive or). The xor operator is useful when comparing two expressions and checking if one but not both are true. In fact, xor is specifically designed for this purpose.

:If A=2 and B≠2 or A≠2 and B=2
can be
:If A=2 xor B=2

Many times a compound expression can be shortened by combining expressions that have the same meaning or replacing expressions that can be written another way. Think about what the expression means and then think about how to make a shorter equivalent expression. There are many ways of writing an expression, so there are usually ways to rewrite it.

:If A>B or A<B
can be
:If A≠B

If you have the not( operator around an expression, you can usually change the logical operator to the math opposite. This allows you to remove the not( operator.

:If not(B=C and A=D
can be
:If B≠C or A≠D

DeMorgan's Law can be used for expressions in which the not operator is around two separate unary expressions joined by the and or or operators. It allows you to remove the second not operator and then change the and to or and vice versa.

:If not(A) and not(B
can be
:If not(A or B

Min is useful when you are comparing one variable or value to several other variables to see if they are all equal to the variable or value. To use min( you just create an expression with the min( function and put the common variable or value inside it followed by an equal sign and a left curly brace. You then list out the variables that you are comparing the variable or value to, separating each one with a comma.

:If A=10 and B=10 and C=10
can be
:If min(10={A,B,C

Max( is useful when you are comparing one variable or value to several other variables to see if at least one is equal to the variable or value. You do the same thing as the min( function, just replacing min with max.

:If A=10 or B=10 or C=10
can be
:If max(10={A,B,C

You can put a comparison operator inside the min( or max( functions to compare when several values or variables are equal to one variable and several values or variables are equal to another variable. This works especially well with three or more variables.

:If A=X and B=U or A=Y and B=V
can be
:If max(A={X,Y} and B={U,V

Abs( is useful when you are comparing a variable to two even or odd values using the or operator. You subtract the larger value from the smaller value, divide the result by two, and then put it on the left side of the equal sign. Next, you subtract the larger value by the result on the left side of the equal sign, and then take the variable being tested and subtract it by that value. You then put the abs( function around the result and place the expression on the right side of the equal sign.

:If A=45 or A=105
can be
:If 30=abs(A-75

X=n1 or X=n2 should become abs(n1-mean({n1,n2}))=abs(X-mean({n1,n2})) (simplified) if n1 and n2 are positive integers and n1+n2 is even. If there are three terms, then see if you can simplify two of them according to this rule. If you can't, then a string of or's will be faster than the max(X={n1,n2,… approach. If there are four terms or more, then use max().

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-logic


Optimization: Loops and Branching

When using loops you want to make them as compact as possible. This starts with moving invariant code outside the loops. You only want loops to contain expressions whose values change within the loops. If something only happens once, it should be outside the loop.

:For(X,1,5
:5→Y
:Disp X
:End
can be
:5→Y
:For(X,1,5
:Disp X
:End

You also want to minimize the calculations inside loops. This not only includes cutting down on the number of storages, but how often variables are used and what they are used for. This can increase the size, however.

:For(X,1,10
:A+length(Str1→A
:End
can be
:length(Str1→B
:For(X,1,10
:A+B→A
:End

Another way to minimize calculations inside loops is to use constant increments. This makes the loop faster, but it also makes it larger.

:For(X,0,10
:Disp 10X
:End
can be
:For(X,0,100,10
:Disp X
:End

You should combine two or more loops that are in close proximity if they use the same number of iterations and don't affect each other. Combining loops may take some ingenuity.

:For(X,1,10
:B+X→B
:End
:For(Y,1,10
:A+A/Y→A
:End
can be
:For(X,1,10
:B+X→B
:A+A/X→A
:End

Loop unrolling reduces the number of times you check the condition in a loop, with two or more of the same statements being executed for each iteration. If the loop is small enough, you can even unroll the whole loop. This will usually increase the size but also make it faster.

:5→dim(L1
:For(X,1,5
:2A→L1(X
:End
can be
:5→dim(L1
:2A→L1(1
:2A→L1(2
:2A→L1(3
:2A→L1(4
:2A→L1(5

For( loops are best used when you know how many times the loop will be executed. Because the fourth argument is optional (one is the default), you should always try to leave it off.

:For(X,1,8,1
:End
can be
:For(X,1,8
:End

You can sometimes rewrite For( loops and the commands inside them so you can remove the fourth argument.

:For(X,8,0,-1
:Disp X
:End
can be
:For(X,0,8
:Disp 8-X
:End

If you have an If conditional around the outside of a For( loop, you should see if there is a way to combine it with the For( loop using Boolean logic.

:If A>10:Then
:For(X,1,50
:End:End
can be
:For(X,1,50(A>10
:End

One of the common uses of For( loops is to slow programs down. Instead of For( loops, you should use rand(# or If dim(rand(#. Both of these create lists of random numbers, with a larger number meaning a larger delay; the second one preserves the Ans variable as well.

:For(X,1,75
:End
can be
:rand(25

This method generally works well for small delays, but it is better to use For( loops for large delays. This is because the rand(# technique is limited by the RAM storage availability, and has a maximum delay of 999 (being a list variable).

:rand(200
can be
:For(X,1,600
:End

Repeat loops will loop until the expression is true, and While loops will loop while the expression is true. Repeat loops are tested at the end of the loop which means they will be executed at least once. This allows you to not always have to set the variables in the expressions, which is the case with While loops. If the expression in a While loop is false before it is tested, the loop will be skipped over. This is sometimes desired if the expression fits that format.

:DelVar A
:While not(A
:getKey→A
:End
can be
:Repeat A
:getKey→A
:End

If you need a loop that loops forever (i.e., an infinite loop), use Repeat 0 or While 1 instead of Goto/Lbl.

:Lbl A
:Disp "Hello
:Goto A
can be
:Repeat 0
:Disp "Hello
:End

Goto/Lbl loops should be used sparingly. When Goto is encountered, it notes the Lbl and proceeds to search for it from top to bottom in the code. This can really be slow if the Lbl is deep within the program. It also has the tendency to make your code harder to follow and maintain. And, if you use a Goto to exit a loop or a conditional that uses an End command, it can lead to memory leaks (causing your program to crash).

:Repeat 0
:getKey→B
:If B
:Goto A
:End
:Lbl A
can be
:Repeat B
:getKey→B
:End

When all a For( loop does is store expressions to a list, you can replace it with a seq( (sequence) command. The sequence command can also be used with other variables.

:5→dim(L1
:For(X,1,5
:2A→L1(X
:End
can be
:seq(2A,X,1,5→L1

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-loops


Optimization: Math Operations and Keys

Multiplication signs are unnecessary and should be removed because the calculator does implicit multiplication. You should remember that implicit multiplication doesn't bind tighter than regular multiplication.

:5*A→B
can be
:5A→B

You don't need to put parentheses around a single variable or number by itself when doing multiplication or division.

:3/(A)
can be
:3/A

Multiplication and division have the same importance based on the order of operations (the rules that determine what order things are evaluated in), so they will be evaluated from left to right if both appear in an expression. If multiplication appears before division, you can remove the parentheses around an expression.

:A+(BA)/5→C
can be
:A+BA/5→C

Although multiplication and division have the same importance in order of operations, multiplication is in fact faster than division when doing math operations. So, you should multiply instead of dividing, especially if doing the multiplication is smaller than doing the division.

:(X+1)/2
:(B+C)/D
can be
:.5(X+1
:Dֿ¹(B+C

When adding a negative number to a positive number, switch the two numbers around and change the addition to subtraction. This allows you to get rid of the negative sign.

:-A+B→C
can be
:B-A→C

You can often times rewrite math expressions using the built-in keys and characters. When you have a number that has two or more zeros, it may be smaller to write it using the the little E character (which is designed for scientific notation). This character will multiply the number on its left (1 if no number is given) times 10 to the number given on the right.

:50000
can be
:5E4

If you want to use a variable to set the exponent of a number, you would have to use 10^X because the calculator doesn't allow ᴇX. This can be replaced with the 10^( key. This also applies to the e^( key, the 2 key, and the 3 character.

:10^A+e²-5²+9³
can be
:10^(A)-52+93+e^(2

If you have a fraction that has one as the numerator, you can replace it with multiplying the denominator by the ֿ¹ key.

:1/16
can be
:16ֿ¹

When you have a fraction that has an expression in the numerator that has parentheses around it and a variable in the denominator, you can sometimes eliminate the fraction by multiplying the variable by the ֿ¹ key and multiplying it by the expression from the numerator.

:If (A+B)/C
can be
:If Cֿ¹(A+B

If you raise a variable or value to some fractional power with one in the numerator, you can just take the denominator of the fractional power and then multiply it by the xroot character and the variable or value.

:A^(1/B
can be
:Bx√A

Always do all the operations you can ahead of time. This eliminates some of the operations that the calculator has to do.

:33+A(8/2→B
can be
:33+4A→B

Write and calculate expressions in one step instead of several steps.

:2BC→D
:3A→E
:D+E→F
can be
:2BC+3A→F

One of the basic math rules is that multiplying one times any variable is equal to the variable. So, you don't need to put the one in front of the variable.

:1A+3→B
can be
:A+3→B

When adding two variables of the same type together, you should add up the number of times the variable appears and multiply that value by the variable.

:A+3A→B
can be
:4A→B

Rewriting division with multiplication is useful when multiplying is smaller. You take the denominator and then change it to the equivalent for multiplication.

:(X+1)/10
can be
:.1(X+1

The distributive identity should be used when you have three or more variables that share a common number or variable. You take that common number or variable out and distribute it to all of the variables.

:CA+CB+C²→D
can be
:C(A+B+C→D

The multiplicative inverse identity is used when you have an expression where the same variable or value is in the numerator and denominator. You can remove the variable or value because it is canceled out.

:2A/(2BA
can be
:1/B

When you have a fraction that has a fraction as its denominator, you can sometimes use the division inverse identity. If the numerator of the first fraction is one, you can flip the second fraction causing the first fraction to disappear.

:1/(4/A
can be
:A/4

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-math


Optimization: Putting Ans Into Practice

The Ans variable (last answer) is a temporary variable that can hold any variable. Ans is changed when there is an expression or variable storage or when pausing with the Pause command. It is mostly useful when you are just manipulating one variable. To use Ans just put an expression on a line by itself; it will automatically be stored to Ans. You can then change the expressions on the next line where the variable was called and put Ans there instead. Ans is faster than normal variables, but slower than Finance/Window variables and constants.

:getKey→A
:B+(A=26)-(A=24→B
can be
:getKey
:B+(Ans=26)-(Ans=24→B

If you have more than one line that calls the variable, you should just keep the variable. However, for the first line that calls the variable you should change the variable to Ans.

:getKey→A
:B+(A=26)-(A=24→B
:C+(A=34)-(A=25→C
can be
:getKey→A
:B+(Ans=26)-(Ans=24→B
:C+(A=34)-(A=25→C

When there is a common expression that is on multiple lines, it is sometimes smaller to put the expression on its own line and then change the expression on the other lines to Ans.

:30+5A→B
:Disp 25A
:Disp 30+5A
can be
:30+5A→B
:Disp 25A
:Disp Ans

When you use the same text many times in close proximity, you should put that text on its own line and replace it with Ans wherever it occurs.

:Disp "Hello
:Disp "Hello
:Disp "Hello
can be
:"Hello
:Disp Ans,Ans,Ans

For complex calculations, there are often multiple parts that are the same. You should take out the most common part and put it on its own line. If there are several common parts, you should take out the part that will result in the greatest size reduction. You then replace that part, wherever it occurs, with Ans.

:2A/(BC)+(BC)2→A
can be
:BC
:2A/Ans+Ans2→A

When dealing with text there are often situations where the same text is repeated multiple times. Rather than writing out the long string of text, it is sometimes possible to rewrite it using Ans. Put the common part of the text on its own line and on the next line concatenate (add together) with Ans however many times is needed to make the string.

:"                     →Str1 //20 spaces
can be
:"      //5 spaces
Ans+Ans+Ans+Ans→Str1

If you use the sub( command to get the appropriate part of some text based on certain conditions, you can sometimes get rid of the sub( command and just use Ans. You would put each piece of text on its own line, and then put the condition before it.

:Input sub("GiveTake",1+4(A=1),4)+" candy?",Str1
can be
:"Give
If A=1:"Take
Input Ans+" candy?", Str1

With Repeat loops, you can sometimes put Ans in the condition instead of the variable. Even if Ans were 0 at the beginning of the loop, the code will work, since a Repeat loop will always cycle once before the condition is checked.

:Repeat A
:getKey→A
:End
can be
:Repeat Ans
:getKey→A
:End

When the condition in a Repeat loop has a common part that is repeated multiple times, you should put the common part at the end of the loop and replace the common part in the condition with Ans.

:Repeat A=2 and B=1 or A=2 and B=3
:getKey
:A+(Ans=26)-(Ans=24→A
:End
can be
:Repeat Ans and B=1 or Ans and B=3
:getKey
:A+(Ans=26)-(Ans=24→A
:A=2
:End

Many times in If-Then-Else conditionals the same expression or string of text appears in both the true and false parts. You should put this expression or string of text before the If-Then-Else conditional and then replace it in the conditional with Ans.

:If B
:Then
:Disp "Hello
:2Bnot(A→C
:Else
:Disp "Hello
:3→D
:End
can be
:"Hello
:If B
:Then
:Disp Ans
:2Bnot(A→C
:Else
:Disp Ans
:3→D
:End

When you have two or more strings of text that share a common part, you should take that common part out. You then can replace it with Ans and concatenate Ans to the strings.

:Disp "Hello World
:Disp "Goodbye World
can be
:"World
:Disp "Hello "+Ans
:Disp "Goodbye "+Ans

When you have two If conditionals that have math opposite conditions and they display text, it is sometimes possible to remove one of the conditionals and use Ans. Take the text from the first condition and put it on its own line. Then put the second conditional and the text on the next line. You then put the display Ans on the last line.

:If A≤B
:Disp "Higher
:If A>B
:Disp "Lower
can be
:"High
:If A>B
:"Low
:If A≠B
:Disp Ans+"er

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-ans


Optimization: Storing Variables

Although it is common to initialize variables for planned use, you should avoid initializing variables that you don't need or that are initialized further down in the program. The reason is because storing to variables really slows a program down (especially inside loops) and there is no point in initializing a variable twice.

:2→A
:If B
:Then
:2→A
:Else
:-2→A
:End
can be
:If B
:Then
:2→A
:Else
:-2→A
:End

When a number is used many times in a program, you should store it to a variable and then just call the variable instead of writing it out every time. This also applies to text that should be put in a string.

:Disp "Hello
:Disp "Hello
:Disp "Hello
can be
:"Hello→Str1
:Disp Str1,Str1,Str1

You can also put common variables or expressions in a string variable and then use the expr( command to reference them. This can be used in conjunction with other variable commands. This also gives you more variables to use.

:Disp 5int(B/7
:Disp 5int(B/7
can be
:"5int(B/7→Str1
:Disp expr(Str1
:Disp expr(Str1

You should reuse variables that have no specific function or that don't need to be saved.

:For(X,1,100
:End
:For(Y,1,50
:End
can be
:For(X,1,100
:End
:For(X,1,50
:End

When storing the same large number in two or more variables, you should store the large number in the first variable and then store the first variable into the rest of the variables.

:7112→A
:7112→B
:7112→C
can be
:7112→A
:A→B
:A→C

When calculating several repetitive trigonometric or other math functions in a program, it is sometimes faster to just store the values in a list and recall the values when needed.

:For(A,0,10
:Text(6A+1,1,10cos(A
:End
can be
:10cos(seq(A,A,0,10→L1
:For(A,0,10
:Text(6A+1,1,L1(A
:End

Matrices are faster than lists, so you should use them in speed sensitive situations, especially if you have 2 lists to store coordinates. While this is much larger, it is also faster.

:Pxl-Off(L1(I),L2(I
can be
:Pxl-Off([A](1,I),[A](2,I

If there are certain constants that arise throughout your program, it can be useful to store those constants to variables. Depending on the size of the constants, this can save a handful of bytes every time the constants are used.

:Line(154,0,154,216
:Line(0,216,154,216
can be
:154→A
:216→B
:Line(A,0,A,B
:Line(0,B,A,B

Note that the initialization of the constants costs extra bytes and a bit of speed. It is best if these values are truly constants that change very little throughout the program, otherwise the speed-to-space sacrifice may not be worthwhile.

<< Displaying Text Table of Contents Math Operations >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-variables


Optimization: The Graph Screen

Although the screen is 95 pixels wide and 63 pixels tall, the bottom row and far right column of pixels are unusable. So, most people set the graphscreen dimensions to 94 and 62. This itself should be replaced with storing 1 into deltaX and deltaY.

:0→Xmin:94→Xmax
:0→Ymin:62→Ymax
can be
:0→Xmin:1→ΔX
:0→Ymin:1→ΔY
can be even better
:ZStandard
:84→Xmin
:72→Ymax
:ZInteger

The Text command can display both variables and text at the same time on the same line. This allows you to sometimes remove multiple Text commands and just use the first one.

:Text(5,5,A
:Text(5,9,"/
:Text(5,13,B
can be
:Text(5,5,A,"/",B

The Pxl-On command is faster than Pt-On, and it should be used whenever possible. Pt-On is also affected by the screen dimensions, while Pxl-On is not.

:Pt-On(5,5
can be
:Pxl-On(5,5

The Line command has an optional fifth argument that controls whether the line will be drawn (the argument should be one) or erased (the argument should be zero). The default is one, and it should be left off when possible.

:Line(5,5,10,5,1
can be
:Line(5,5,10,5

When turning multiple pixels in a straight line on or off, use a For loop instead of using the individual pixel commands.

:Pxl-On(5,5
:Pxl-On(5,6
:Pxl-On(5,7
:Pxl-On(5,8
can be
:For(X,5,8
:Pxl-On(5,X
:End

When you are changing the same pixels from on to off or vice versa in a loop, use the Pxl-Change command instead of the individual pixel commands.

:For(X,5,8
:Pxl-On(5,X
:End
:For(X,5,8
:Pxl-Off(5,X
:End
can be
:For(N,1,2
:For(X,5,8
:Pxl-Change(5,X
:End
:End

When you have multiple pixels in a straight line that you turn on or off, you can sometimes replace the Pxl-On commands with Line commands.

:Pxl-On(5,5
:Pxl-On(5,6
:Pxl-On(5,7
:Pxl-On(5,8
can be
:Line(5,5,5,8

The Pt-On and Pt-Off commands have an optional third argument that should never be used when one is desired because one is the default.

:Pt-On(5,5,1
can be
:Pt-On(5,5

The optional third argument for Pt-On and Pt-Off should be used when you want to turn on or off a 3x3 outline of a box (the argument should be two) or a 3x3 cross (the argument should be three). This can be used instead of the individual commands.

:Pt-On(A,B-1
:Pt-On(A,B
:Pt-On(A,B+1
:Pt-On(A-1,B
:Pt-On(A+1,B
can be
:Pt-On(A,B,3

When wanting to clear large spaces of the graph screen, you should use the Line or Text commands instead of the pixel commands, when possible. Both of these commands are faster than the pixel commands.

:Pxl-Off(5,5
:Pxl-Off(5,6
:Pxl-Off(5,7
:Pxl-Off(5,8
can be
:Line(5,5,5,8,0

The Circle( command has an alternate syntax. When a complex list such as {i} is added as the 4th argument, "fast circle" mode will be turned on, which uses the symmetries of a circle to save on trig calculations, and draws a circle in only 30% of the time it would normally take. Since the Circle( command is speed-challenged at best, you should always use this optimization when drawing circles.

:Circle(0,0,5
can be
:Circle(0,0,5,{i
<< Loops Table of Contents Summary >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-graph


Optimization: User Input

The Input command has an optional display message argument that can be either text or a string. This display message can be used to tell the user what type of value to enter or to show what the variable is for. The Input command should be used instead of using a Disp command in conjunction with the Prompt command.

:Disp "Guess
:Prompt A
can be
:Input "Guess?",A

If you have two Input commands that have display messages that are positioned between a conditional, you can often remove one of the Input commands and then use the sub command to display the appropriate display message. This allows you to get rid of the conditional. You can also take out the common part of the display message and add it to the substring part of the display message.

:If A=1
:Then
:Input "Take candy?",Str1
:Else
:Input "Give candy?",Str1
:End
can be
:Input sub("GiveTake",1+4(A=1),4)+" candy?",Str1

The Prompt command can be used with more than one variable. If you have a list of prompt commands, you should put all of the variables on the first Prompt command, separating each variable with a comma. This allows you to get rid of the rest of the Prompt commands.

:Prompt A
:Prompt B
:Prompt C
can be
:Prompt A,B,C

The Prompt command should be used instead of the Input command when you have the display message show what the variable being stored to is. And if there are multiple Input commands, you can reduce them to just one Prompt command.

:Input "A=?",A
:Input "B=?",B
:Input "C=?",C
can be
:Prompt A,B,C

When doing calculations and user input, you should move the calculations before the user input. The delay before the user input is not important because people simply can't type fast enough to notice it.

:Input "NAME:",Str1
:3B/7→L1(1
:2A+5B→C
can be
:3B/7→L1(1
:2A+5B→C
:Input "NAME:",Str1

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-input


Optimizations: Displaying Text

If you have a string of numbers that you are displaying, you don't need to put quotes around the numbers. You should only use quotes if you want to keep any leading zeros.

:Disp "2345
can be
:Disp 2345

Use the Disp command instead of the Output command when displaying text on the first line of the homescreen. You can just add spaces to the text to move it to the correct location.

:Output(1,2,"Hello
can be
:Disp " Hello

When displaying the same text or variable on three or more lines, use a For loop. A For loop can also be used when the display is changing by a constant increment.

:Output(3,3,1
:Output(4,3,2
:Output(5,3,3
can be
:For(X,3,5
:Output(X,3,X-2
:End

When the text in an Output command is more than sixteen characters, it will wrap around to the next line. When you have two or more Output commands that display text on different lines, you can sometimes put the text together and add blank spaces between it to make it go to the next line in the desired location.

:Output(1,6,"Hello World
:Output(2,2,"Version 1.0
can be
:Output(1,6,"Hello World Version 1.0

Using the Disp command, you can display text and variables at the same time by putting a comma between each one. Because this can hinder readability, this should only be done when just displaying variables.

:Disp A
:Disp B
can be
:Disp A,B

When you have a list of Disp commands that you pause, you can take the text or variable from the last Disp command and place it after the Pause command as its optional argument, allowing you to remove the last Disp command.

:Disp "A=
:Disp A
:Pause
can be
:Disp "A=
:Pause A

You can often remove Disp commands by storing to a string only the text differing with values of a variable, and then displaying the text added to the similar statements with one Disp command. This can be useful when you have two conditionals that are opposites that display similar text.

:If A≥10
:Disp "You Win
:If A<10
:Disp "You Lose
can be
:"Win
:If A<10
:"Lose
:Disp "You"+Ans

When you have two or more Disp statements inside an If-Then conditional, you can combine the Disp statements to change the If-Then conditional to an If conditional.

:If A>B
:Then
:Disp "A is greater
:Disp "than B
:End
can be
:If A>B
:Disp "A is greater","than B

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/optimize-text


The newList() Command

newlist.png

Command Summary

Returns a list filled with zeroes.

Command Syntax

newList(length)

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The newList() command returns a list of a specific length that is filled entirely with zeroes.

:newList(3)
           {0  0  0}
:newList(5)
           {0  0  0  0  0}
:newList(0)
           {}

This can be easily expanded to returning a list filled with any value: to return a list filled with a value x, just add x to the result of newList(). This works for strings as well, since "Hello"+0 simplifies to "Hello".

Advanced Uses

newList() can be used for making a comparison between a single value and a list. Normally, something like {1,2,3,4}=2 simply returns "false", since 2 is not a list and {1,2,3,4} is. To do a comparison element-by-element, use newList() to turn the single value into a list: in this case, 2+newList(4). Comparing {1,2,3,4} to 2+newList(4) will return {false, true, false, false} (you might use when() to get a single value out of this list).

This works to extend other operations to a number and a list, as well, though comparisons are the most useful application of this technique, since most operations already work this way.

Optimization

In many cases, an expression with newList() can be used to optimize a seq() command. First, observe that the simple

:seq(k,k,1,n)

which will return the list {1,2,3,…,n}, can be replaced by
:cumSum(1+newList(n))

The result is about twice as fast.

This is useful because many seq() expressions can be expressed using something like seq(k,k,1,n). For example:

:seq(k^2,k,1,n)

can be

:seq(k,k,1,n)^2

which is

:cumSum(1+newList(n))^2

This rearrangement is not always possible, but when it is, it gives a significant improvement in speed, with no real difference in size.

Here is a more complicated example (which is a sequence of probabilities with the binomial distribution). Notice the use of the with operator.

:seq(nCr(n,k) p^k (1-p)^(n-k),k,1,n)

can be

:nCr(n,a) p^a (1-p)^(n-a)|a=cumSum(1+newList(n))

Error Conditions

260 - Domain error happens when the length is not an integer ≥0.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:newlist


Piecewise Expressions

Piecewise expressions are a shortcut to handling conditions in math statements. They can be used for turning an If block or several such blocks into a single line. Although the TI-83 manual recommends them for graphing piecewise functions, they are very important to programmers as well — it would not be an overstatement to say that the use of piecewise expressions revolutionized TI-Basic when it was introduced. On recent operating systems (5.3+) for the TI-84+ CE, the piecewise( command was added, and it lets you see piecewise expressions on the homescreen and y= screen as they would be seen in a math textbook, if mathprint is on.

The Concept

The general form of a piecewise expression is (expr #1)(condition #1)+(expr #2)(condition #2)+…→result. Usually, condition #1, condition #2, and any other conditions are mutually exclusive — only one of them can be true at a time. In this case, the piecewise expression can be interpreted as follows:

  • if condition #1 is true, return the value of expr #1
  • if condition #2 is true, return the value of expr #2
  • if condition #n is true, return the value of expr #n

A classic example of a piecewise function is absolute value, which strips a number of its sign. Forget for a moment that the abs( command exists, and picture code that would do its job. A possible solution relies on the If command:

:If A≥0
:Then
:A→B
:Else
:-A→B
:End

Using piecewise expressions, we can write this as:

:(A)(A≥0)+(-A)(A<0)→B

Most of the parentheses are unnecessary, only here for clarity. If you're comfortable with piecewise expressions, you can strip the extra parentheses to get this version:

:A(A≥0)-A(A<0→B

Why does this work?

Believe it or not, the calculator does not make special cases for piecewise expressions. Instead, this technique relies on the convention known as Boolean logic. According to Boolean logic the number 1 represents "true" in logical expressions on the TI-83, while 0 represents "false".

In the case of a properly written piecewise expression, only one of the conditions will be true, and the rest will be false. That condition's expression will be multiplied by 1, and the others by 0. When the results are added, this gets rid of the unwanted expressions, leaving only the one with a true condition.

Optimization

Now that we know how this technique works, we can optimize such expressions while keeping the result the same. For example, here is part of the code for moving a cursor on the screen, as a piecewise expression:

:getKey→K
:(X-1)(Ans=24)+(X+1)(Ans=26)+(X)(Ans≠24 and Ans≠26)→X
:(Y-1)(K=34)+(Y+1)(K=25)+(Y)(K≠34 and K≠25)→Y

Notice that all three pieces of the first expression contain X, and all three pieces of the second expression contain Y. In such cases, we can take out the common part of the pieces, without changing the result:

:getKey→K
:X-(1)(Ans=24)+(1)(Ans=26)+(0)(Ans≠24 and Ans≠26)→X
:Y-(1)(K=34)+(1)(K=25)+(0)(K≠34 and K≠25)→Y

Finally, we can cancel the unneeded parts. Many of the parentheses are unnecessary, but it's also pointless to multiply something by 1, so we can get rid of the (1) parts entirely. Finally, the parts multiplied by 0 are redundant.

:getKey→K
:X-(Ans=24)+(Ans=26→X
:Y-(K=34)+(K=25→Y

The result is the movement code you may have seen elsewhere in the guide, in its fully optimized form!

Advantages and Disadvantages

Piecewise expressions are usually a better choice than clunky If statements to accomplish the same thing. They give the following benefits:

  • The result is usually faster to compute, and takes less memory in the program.
  • The expression takes less space on the screen to scroll through.
  • Piecewise expressions can be used where If statements can't (for example, equations).

However, there are a few drawbacks you need to be aware of:

  • Unlike an If statement, a piecewise expression will compute all its parts before returning the result.
  • Complicated logic can make piecewise expressions very messy and hard to understand.

So one situation in which piecewise expressions should be avoided is one in which part of the expression takes a long time to compute. For example:

:If N=1
:Then
:irr(I,100,L1→P
:Else
:P(1+.01I→P
:End

In this case, a very complicated calculation is done in the case N=1 (if L1 is large enough, it may take several seconds). But if N is not 1, the calculation is very simple and will finish quickly. If you made this code a piecewise expression, the very complicated calculation would always be calculated, even if it's not going to be necessary.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/piecewise-expressions


Friendly Graphing Window

A friendly graphing window is some configuration of window variables that's most useful for your program — most commonly, because it makes the coordinate value of a pixel come out to a round value, such as an integer, or .1 of an integer.

Setting up a square window

The most basic type of friendly window is one in which a vertical distance in pixels is equal, coordinate-wise, to the same horizontal distance in pixels. This means that the ratio between (Xmax-Xmin) and (Ymax-Ymin) is 47:31. Such a setup has the useful effect that drawing a circle (for example, with the Circle( command) actually results in a circle, and not an ellipse.

This can be accomplished simply with the ZSquare command, which will alter the values of the screen so that:

  • the coordinate of the center remains the same
  • the ratio (Xmax-Xmin) : (Ymax-Ymin) is 47:31 (approximately 1.516 : 1)
  • the resulting window is larger rather than smaller than the original.

A common technique is to run the ZStandard command first, so that the center of the screen is at (0,0).

Setting up an integer square window

However, it's possible to take friendliness even further, by adding the condition that coordinate values of a pixel come out to round values without long decimals. This can be done in several ways:

Using the ZDecimal command

This is by far the simplest — the ZDecimal command will set Xmin to -4.7, Xmax to 4.7, Ymin to -3.1, and Ymax to 3.1. As you can see, this satisfies the condition for a square window. Also, the coordinates of pixels have at most one decimal place: pixels that are next to each other differ by 0.1 in the appropriate coordinate.

Zdecimal is useful if you only need to do a few point/line commands, like if you were drawing a border around the screen using Horizontal and Vertical.

However, it has the drawback of still having a decimal point. Your drawing commands may look like Line(-3.1, -1.7, 3.1, -1.7) — if you didn't have to have that decimal point there, you'd save a considerable amount of space. This is possible, using the following three methods:

An integer window with (0,0) in the center

These methods are basically divided over where the point (0,0) should be. Putting it in the center ensures that drawing things in the middle of the screen takes up little space; also, you can achieve symmetry easily by appropriately negating numbers. On the other hand, the negative sign (you'll be using one 3/4 of the time, and 1/4 of the time you'll need two) can be annoying.

The following code sets up an integer square window with (0,0) in the center:

:ZStandard
:ZInteger
An integer window with (0,0) in the bottom left corner

This approach is optimal in terms of saving space on coordinates: they are all positive numbers with at most two digits. For this reason, it is the most widely used. The following code sets up such a window:

:ZStandard
:84→Xmin
:72→Ymax
:ZInteger
An integer window with (0,0) in the top left corner

This approach is useful for when point and pixel commands need to be used together. Although putting (0,0) in the top left makes every Y-coordinate negative, the window has the useful property that it's very easy to go from point commands to pixel commands: the pixel (R,C) corresponds to the point (C,-R), and equivalently, the point (X,Y) corresponds to the pixel (-Y,X). It's somewhat trickier to set up, though:

:ZStandard
:84→Xmin
:-72→Ymin
:ZInteger

Why friendly windows are useful

Throughout this article, we've only made glancing comments as to why you'd want to use friendly windows. Here is a more exhaustive explanation:

Graphs come out nicer

Even with a square window, graphs become more accurate, because they reflect the actual proportions of the equation being graphed. For example, try drawing a circle in the standard graphing window — you'll get some stretched out oval. Now ZSquare and try again. The result is much better, right?

With an integer square window, certain other imperfections of the calculator's graphing go away. For example, try graphing Y=1/(X+1) in the standard graphing window. Pretty accurate, but instead of the asymptote there's a slightly diagonal line. That's because the asymptote doesn't end up corresponding to a pixel of the graph: one pixel, the curve is a very negative number, the next it's a very positive number, so the calculator tries to connect them.

Now ZDecimal and graph 1/(X+1) again. The nearly vertical line at the asymptote disappears: because the value X=-1 matches a pixel on the graph, so the calculator realizes that something is undefined there.

Another similar problem occurs with graphing Y={-1,1}√(9-X²). In most graphing windows, this graph, which should come out to a circle, has some gaps near the sides. In an integer square window, such as with ZDecimal, the gaps disappear, and you're left with a perfect circle.

Coordinates are round numbers

This is a more programming-related application. If you happen to need to draw something on the screen, in a program, you're likely to need a lot of Line( or Pt-On( commands at fairly specific locations. On a normal window, such a "specific location" might end up being (2.553,0.645) or something equally ugly, with unpredictable results if you try to round it to the nearest nice value (since you don't know exactly the point at which pixels change).

With a friendly window (for this purpose, an integer window with (0,0) in the bottom left is the friendliest), every single pixel has a round coordinate value. If each value is no more than a 2-digit number, you can even compress all the coordinates of a line into a single number — this technique was used, for example, in Bryan Thomas' Contra game.

Point and pixel commands are compatible

In the case of an arbitrary window, it's fairly difficult to convert from a pixel coordinate to a point coordinate and back: the exact formula is X=Xmin+CΔX, Y=Ymax-RΔY if (X,Y) is the point and (R,C) is the pixel (going from pixel to point is even more painful). However, there are many cases in which you do need to go back and forth — for example, if you need to draw both text and lines at a coordinate. With friendly windows, this formula becomes much simpler — such as (X,Y)=(C,-R) for the last integer window we discussed.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/friendly-window


Animation

Animation is the rapid display of images on the screen to create an appearance of movement: it works by displaying an image and then moving it to a new location after a short delay has occurred. While there are many different things that you can do for animation (the possibilities are practically infinite; heck, there is an entire program directory at ticalc.org devoted to animations), almost every animation depends on For( loops.

A For( loop is a special kind of While loop, with all of the loop construction built-in, it has the the variable that the loop uses, the starting value, the ending value, and the increment. This is important because you can use all of those things to dictate how many times the animation is displayed, the speed of the animation, and even the animation itself (using the For( loop variable as the coordinates or the text that is displayed).

Animation is commonly used at the beginning of a program or on loading screens to add some visual pop or pizazz, which gives a program an edge over similar programs. At the same time, this does not mean that you can't go overboard with animation; too much animation becomes annoying and lengthy after a while. Selective animation — where it makes sense and complements the program — has the best impact in a program.

You also want to keep in mind the calculator that the animation is running on. If you created your animation on the TI-83+SE or TI-84+SE, then the animation probably won't display as you intended on a TI-83 or TI-83+ calculator (calculators that have a much slower processor; 6MHZ and 8MHZ respectively are slower compared to 15MHZ for the TI-83+SE and TI-84+SE). Of course, there are a few other things that you need to consider, so you should read the portability page for more information.

Animation Examples

This is an example of moving text: the variables of the X or Y coordinate of the text are changed by the for( command.
The spaces before "looks" and after "huh?" are needed to delete the old text.

ClrDraw
AxesOff
For(A,1,20
Text(A,40,"This
End
For(A,1,19
Text(28,A+9," looks
Text(28,69-A,"cool
End
For(A,50,35,-1
Text(A,40,"huh?
Text(A+6,40,"<16 spaces>
End
Running this code gives this program:
Text_example_looped.gif

TODO: Add more examples

  • Using pictures
  • Drawing/Erasing text (changing position, size, letter by letter)
  • Drawing/Erasing shapes (changing position, size, color)
  • Drawing/Erasing lines (changing position, size, color)

One of the most common examples of animation that you see in games is wiping the graph screen (you can certainly wipe the home screen as well). This is usually done at the end of the game, after the player has lost, or as a transition from one level of the game to the next.

Wiping the screen involves using one or more Line( or Horizontal/Vertical commands, and then displaying the line from one side of the screen to the other:

:For(X,Xmin,Xmax,ΔX
:Vertical X
:End

As you can see, a vertical line is displayed from the left side of the screen to the right side, effectively shading the entire screen. Since it uses Xmin,Xmax, and ΔX, it will work on any screen.

Another common example is displaying text. This is commonly used on the titlescreen of a game to make the game stand out to the user. There are several different ways that you can display text, but some of the most common are: letter by letter, sliding it in from the screen side, overlapping each letter, and displaying the large text behind the small text.

Displaying text letter by letter involves placing the text in a string, and then displaying the respective substring based on where you are in the For( loop. More plainly stated, display each character by itself at the respective time.

The code for this is fairly simple:

:For(X,1,5
:Output(1,X,sub("HELLO",X,1
:End

Animation Length

The two different options for animation length are timed and infinite: timed means the animation lasts for a set amount of loop iterations, while infinite means the animation will go on indefinitely with no end (or at least until the user finally presses the ON key).

The way you go about making a timed animation is by simply using an additional For( loop enclosed around the animation. For example, if you want the animation from before to be displayed five times, you can just do:

:For(I,1,5
...
:End

There are actually two different ways to make an infinite animation: use a For( loop with a really large ending value (such as E5) or use an infinite While 1 or Repeat 0 loop. The infinite While or Repeat loop is the smaller of the two, but the For( loop has the advantage that it still allows the user to exit out of the animation.

Of course, the really long For( loop is not a true infinite loop, since it will eventually end at some point. For our purposes, however, it works quite well because the calculator will actually power down after a certain amount of inactivity (the TI-83+ and above have a built-in APD feature).

Adding a Delay

If you try out any of the examples that have been shown so far, one of the things you will probably notice is that they display so quickly that you can barely see them being displayed until they are almost done. This behavior is acceptable for some animations, such as where there is lot of things being animated at one time, but it can cause havoc for a lot of animations. The way you fix this problem is by adding a delay.

There are two basic ways to create a delay: use a For( loop or use the rand command. The For( loop is just an empty loop, meaning there are no commands or functions inside of it. The rand command's alternate syntax — rand( — generates a list of random numbers, which is a rather time-consuming operation. Both of these delay methods can be worked so that they create a small or large delay simply by changing the size of the For( loop and the number of random numbers generated respectively.

For an example, here is the text animation from before, where the word HELLO is displayed letter by letter on the first line on the home screen, with each of the two respective delay methods added to it:

:For(X,1,5
:Output(1,X,sub("HELLO",X,1
:For(I,1,20:End
:End
:For(X,1,5
:Output(1,X,sub("HELLO",X,1
:rand(10
:End

Each delay method has its own advantages and disadvantages. The For( loop has the advantages that using it still allows the user to do something during the delay, and it does not have any additional memory overhead like rand does. The rand command has the advantage that it is smaller in size than the For( loop.

The rand command does use some additional memory for storing the temporary list of random numbers in Ans, which may be undesirable. To avoid this, you simply have to use this somewhat longer line: If dim(rand(#. Despite the presence of an If statement, you don't have to worry about the next line being skipped, since dim(rand(#)) will always be true.

The other concern when using the rand command is that if the number is large enough, the program will run out of memory from trying to generate such a large list, and subsequently return a ERR:MEMORY error. What number is too large is dependent on how much free RAM is available on the calculator, so for some people it might be 100 while for others it might only be 50. So, if you want to use a large delay, it might be better to go with a For( loop instead of a rand command.

Related to that concern is the issue of portability: a delay may be appropriate on your calculator, but it won't be on another calculator. For example, if you have a TI-83 and you use a delay for twenty iterations of a For( loop, that would be almost unnoticeable on the much speedier TI-83+SE and TI-84+SE calculators. Conversely, if you write your program on a TI-83+SE, the delay would be much longer on a TI-83 and TI-83+, to the point that the animation would slow to a crawl.

With exception to assembly libraries, there is no viable way to check what calculator a program is being run on. A good alternative is to find the appropriate delay for each calculator, and then take the average for the delay that you use. This happy medium is just a simple fix, and really all you can do is just keep the other calculators in mind when deciding how much delay to use.

Allowing User Exiting

One of the main considerations that you have to make when using animation in a program is whether the user can exit the animation at any time they want. This applies to animations of any length, but it especially applies to long animations. This is because the user has to wait until the entire animation is finished before they can move on to the rest of the program, which is extremely annoying from the user's point of view (see program usability for more information).

There are a couple different ways you can fix this problem. The first way is to add some getKey's throughout the animation to check for user key presses; and if you find any, you exit the animation.

Since the animations use For( loops, and we want to exit out of them before they have finished, you can do this by storing something at least equal to the end value to the variable used in the For( loop. For example:

:For(C,61,32,-1
:Pxl-On(C,47
:If getKey:32→C
:End

While this approach works quite well if your animation only consists of one For( loop, it doesn't work when you have two or more For( loops that you need to exit out of. The problem is that if you exit out of the first loop early, you then need to skip the rest of the For( loops in the animation.

Unfortunately, there is no real easy way to go about doing this. One option is to use branching to jump out of the For( loops to go to a While 0 loop internal subprogram. The reason for doing this, of course, is to avoid creating a memory leak.

Because using branching can get rather messy, another option is using an additional variable to act as a flag. You just set the variable to an off state (zero is the standard value), and then change it to an on state (achieved by inverting the flag variable's value) when the user has pressed a key.

For example, here is an animation that displays the word HELLO letter by letter, and then erases each letter starting from the "O". If the user doesn't exit the animation early, it will be played 100 times before it is finally finished. Note the first example uses the branching while the second example uses the A variable as a flag.

:For(I,1,E2
:For(X,1,5
:Output(1,X,sub("HELLO",X,1
:If getKey:Goto A
:rand(10
:End
:For(X,1,5
:Output(1,6-X," "
:If getKey:Goto A
:rand(10
:End:End
:While 0:While 0
:Lbl A
:End:End
:DelVar A
:For(I,1,E2not(A
:For(X,1,5not(A
:Output(1,X,sub("HELLO",X,1
:If getKey:not(A→A
:rand(10
:End
:For(X,1,5not(A
:Output(1,6-X," "
:If getKey:not(A→A
:rand(10
:End
:End

Those two options should generally suffice for most animations, but a third option available is to simply rewrite the animation. There is no hard and fast way to rewrite an animation, but it generally just involves thinking about the animation and seeing if there is an alternative way of implementing it.

One common way to rewrite animations where you are moving back and forth (or displaying and erasing text) is by combining the two For( loops into one, and using some additional variables to keep track of the current direction (or if it should be displayed or erased). When an edge is reached, you then just invert the variables values from negative to positive and vice versa.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/animation


Custom Menus

Menus are often used in programs to choose options, allowing a program to have multiple functions, or a game to have extra features. Though the Menu( command creates a perfectly functional menu, sometimes you want your program to use something more fancy, to have a differently-functioning menu, or just to stand out from the others with a menu that looks different.

However, a custom menu is usually 2 to 3 times the size of the same menu written with the Menu( command - the difference is between a menu that takes up 150-200 bytes and one that takes up 50-100 bytes.

Basic Menus

This covers the basics of creating a functioning custom menu. Remember to set up the graph screen before displaying the menu, to avoid something like axes covering the menu.

Numerical Input

The simplest way to create a custom menu is just to display the title, and a numbered set of options. Then, wait for a number key to be pressed, and act accordingly.

The following code is an efficient way of waiting until a number key is pressed, and converting it to a number N:

:Repeat 2>abs(5-abs(5-abs(Ans-83)))
:getKey
:End
:round(13fPart(Ans/13))→N

But you might not always need to convert the number at all. If all you're going to do with the option is go to a different part of your code, you might just want to use the getKey value for comparisons. And if you only have a small number of options, it's easier to check for them all explicitly rather than using the abs( command as above: for example, Repeat max(Ans={92,93,94}) will check for the keys 1, 2, and 3.

Arrow Key Input

If you want to get slightly more fancy, you could provide a cursor, such as an arrow or ">" symbol, that points to the selected option (there are many ways to display this). The first thing you'd do is display the title and the options, just as in the previous case (except you wouldn't need to number them). Then create a variable that stores the option currently chosen.

For the rest of the code, you would need a loop, structured roughly as follows:

Loop until a selecting key (such as enter) is pressed
Display a cursor at the currently chosen option
Wait for a key to be pressed
Erase the cursor
If an arrow key was pressed, change the chosen option variable
End of the loop

It is important that you actually wait for a key to be pressed, instead of just storing the key to getKey. The loop will work both ways, but if you don't wait for the key, then it will go through the loop even when no key is pressed, erasing and redrawing the cursor, which causes flicker. Another way to eliminate the flicker is to only erase the cursor if an arrow key was pressed.

You can use Boolean optimizations to quickly adjust the option based on the arrow keys:

:N+(K=34 and N<(# of options))-(K=25 and N>1→N

Another possible optimization is to use the row coordinate of the option, rather than the option number, for the value you store (but then you need to modify it by the row difference between two options, rather than 1, when arrow keys are pressed)

Labels vs. Values

The Menu( command goes to a label when an option is selected, whereas both of these methods return a value. It's fairly easy to go back and forth between these methods. To convert from a value to going to labels, add If statements like:

:If N=92
:Goto 1

To convert the Menu( command from going to labels to returning a value, use code like this:

:1
:Menu("TITLE","OPTION 1",1,"OPTION 2",2,"OPTION 3",3
:Lbl 3:Ans+1
:Lbl 2:Ans+1
:Lbl 1

1 is stored to Ans. If 1 is chosen, the Menu( command goes to Lbl 1, and this code finishes with Ans=1. If 2 is chosen, the Menu( command goes to Lbl 2, where Ans is increased to 2, then the code goes to Lbl 1 and finishes. If 3 is chosen, the Menu( command goes to Lbl 3, which has 2 Ans+1 commands after it, so Ans is increased twice: to 3.

However, it's usually easy to avoid using labels with menus.

Advanced Menus

This section covers advanced techniques your custom menus might use.

Multi-page Menu

(this section is based on this menu routine by Steve Hartmann)

A multi-page menu could be used for as many options as you wanted, and is another reason to use a custom menu routine. To create a multi-page menu, you would need a loop which displays the current page (most likely with some If statements), then does the necessary operations for a normal menu until either an option is selected or the left/right arrow keys are pressed. If an option is selected, obviously you exit the loop; otherwise, you change the page number but stay in the loop.

The most complicated situation you could be in is a multi-page menu operated completely by arrow keys. Here, you'd use a total of three nested loops: one for the page, another for the menu itself, and a third for waiting for a key.

Selecting Options

In an arrow-key operated menu, you have several options for the cursor. The simplest is to draw some sort of symbol next to the option currently selected. This could be embellished by animating the symbol - a little tricky, because it must be done inside a getKey loop. Here is an outline of the code to do so:

:Repeat K
:For(I,1,(some limit))
:(draw Ith step of animation)
:getKey→K
:I+(limit)*Ans→I
:End
:End

Inside the getKey loop, a For( loop goes through all the frames of an operation. This by itself would take too much time - even if you pressed a key, you would have to wait for the animation to cycle entirely. To prevent this, we add the line I+(limit)*Ans→I. Ans holds the value of getKey, which is 0 if no key was pressed, and not zero otherwise. So if no key was pressed, we're adding 0 to I, which does nothing. If a key was pressed, however, we add a large value to I which puts it beyond the range of the For( loop, to exit the For( loop immediately. If the For( loop has a small limit, like For(I,1,10), you can simply add getKey to I, since getKey is at least 11 if it's not 0.

Program Structure

Most people reading this page probably are familiar with the reasons to avoid Goto and labels, and do stay away from them usually. However, menus complicate the situation enough that a lot of calculator programmers give up and use labels anyway, creating a program that's impossible to understand or to maintain because of the complex web of Goto commands. This doesn't need to happen - you can structure your code so that labels are unnecessary. The important part is to create this structure first, and then build the program around it, rather than writing a program and trying to tack a menu onto it later.

Suppose your menu chooses among several options which should run and go back to the menu, and a final Quit option. The structure for your program could look like this:

:Repeat choice=Quit
:(menu that sets 'choice')
:If choice=Option 1:Then
:(run option 1)
:End
...
:If choice=Option 35:Then
:(run option 35)
:End
:End (the outermost loop)

The weakness in this code is that the variable your choice is stored in can't be modified by any of the options, or else you risk setting it to the value of an option that's yet to be checked for (which in that case will also run before you get back to the menu). To get around this, any options that modify this variable should DelVar it at the end of their If-Then-End block, then it won't interfere with anything else (theoretically, you could use the variable Ans, and then instead of DelVar add the line :0)

Examples

Some sample programs with a simple number menu, cursor-based menu, and animated cursor-based menu:

You can also download all three in one file.

You can find a sample multi-page custom menu program here.

Scroll Bar

Moreover, you can add a vertical scroll bar. The scroll bar is a nice feature which not only looks good but also gives the user an overview of the menu.

First, you need some variables. You can use a list, in this case L(SCBAR).

1 PStart The point where the scroll bar starts
2 PEnd The point where the scroll bar ends
3 ETotal All of your options or elements in total
4 EAbove All of the invisible options above the visible elements
5 EBelow All of the invisible options below the visible elements
6 LStart Point where the scroll bar would start if 100% of the elements were visible
7 LEnd Point where the scroll bar would end if 100% of the elements were visible

First, we need to calculate PStart and PEnd:

LSCBAR(6)+LSCBAR(4)*((LSCBAR(7)-LSCBAR(6))/LSCBAR(3))->LSCBAR(1) // P,,Start,, = L,,Start,, + E,,Above,, * (L,,End,, - L,,Start,,)/E,,Total,,
LSCBAR(7)-LSCBAR(5)*((LSCBAR(7)-LSCBAR(6))/LSCBAR(3))->LSCBAR(2) // P,,End,, = L,,End,, + E,,Below,, * (L,,End,, - L,,Start,,)/E,,Total,,

Simple percent math ;)

For the scroll bar you just draw 3 lines:

Line(93,-LSCBAR(1),93,-LSCBAR(2) // 93 is the X-Coordinate where the scroll bar will be drawn
Line(92,-LSCBAR(1)-1,92,-LSCBAR(2)+1 // Makes the scroll bar look better
Line(94,-LSCBAR(1)-1,94,-LSCBAR(2)+1

Finally, you could theoratically also draw a horizontal scroll bar, you just need to replace the variables with other values and the line commands.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/custommenus


Saving

The most efficient and versatile way to save data when a program exits is by using a custom list. The list can be named after your program, hold up to 999 values, and be archived for long-term storage. Below is an example of a simple saving routine that backs up the variables A,B, and C into ∟SAVE and archives the list. It then unarchives and restores the data from that list.

:{A,B,C→SAVE
:Archive ∟SAVE
:SetUpEditor SAVE
:If not(dim(∟SAVE
:{0,0,0→SAVE
:∟SAVE(1→A
:∟SAVE(2→B
:∟SAVE(3→C

The Explanation

First, use the syntax {value, value, value, …}→SAVE to back up as many values (usually variables) as you want. If ∟SAVE does not exist, it will be created with those values. If it does, the previous data will be overwritten and replaced.

:{A,B,C→SAVE

To prevent losing saved data, the list is stored in Archive memory. While in Archive memory, it will not be erased due to a RAM clear and cannot be overwritten by other programs. You might consider leaving this step out, however, to preserve compatibility with the TI-83 (which doesn't have Archive memory).

:Archive ∟SAVE

To load the saved data, it first must be moved out of archive memory, or an ERR:ARCHIVED will result. The most obvious method would be to use Unarchive ∟SAVE. However, using this command will cause problems if the list does not exist. The best command to use is SetUpEditor, which was intended for use with the built-in list editor.

As a side effect of setting up a list in the editor, SetUpEditor will create the list if it does not exist, unarchive it in archive memory, or leave it alone in RAM. In other words, SetUpEditor will always result in an unarchived ∟SAVE in RAM, without any errors (also see the relevant section on program cleanup). SetUpEditor can also be used on multiple lists separated by a comma.

:SetUpEditor SAVE

But what happens if this is the first time we're running the program? The answer is SetUpEditor will create our list for us, but it will have a length of 0. This allows us to check if we've saved data to it before: if we have, hopefully, it will have a length of more than that (in this case, 3). So this piece of code stores a default of {0,0,0} to the list if it's just been created (of course, you can put in anything you want as the default, or do something else entirely).

:If not(dim(∟SAVE
:{0,0,0→SAVE

Lastly, the stored data values are recalled into the variables to be restored.

:∟SAVE(1→A
:∟SAVE(2→B
:∟SAVE(3→C

Alternative Methods

You can also modify list entries (auto-save) directly during the game. Doing so saves the user from having to save the game before exiting, but may take more memory.
If you give the player the option to save in a linear/preset game, you can use variables and the Sto> key to create a way to save without using a list. This method branches off, and is infinitely expandable. Here is an example:

:ClrHome:Menu("Game","New",1,"Load",2,"Exit",3) 
:Lbl 2      // Ignore the other options for learning purposes. 
:If X=2
:Goto 45 :End     // Loads from where the player left off
...
:Menu("Save?","Yes",A,"No",45) 
:Lbl A :X → 2 :Goto 45 :End 
:Lbl 45 :Disp "Hi!" 
...     //Rest of code

Protecting Saved Games

It's quite a pain when you go through all that trouble to get users to follow the game through its entirety without the user changing his/her list data to give himself/herself ultimate powers. There are a few ways to protect this from happening.

Addition Method

To protect your saved lists, you can add up all the values of the list and store it to an element in the list right before the program leaves, and check it before allowing the user to reload that saved game.

Right before quitting:

:sum(∟SAVE,2→∟SAVE(1    // list element 1 is used to save the summation of all other list elements

Checking to make sure list elements add up:

:If sum(∟SAVE)≠2∟SAVE(1
:Disp "ERROR: DATA CORRUPTED

Extra list elements

Another method available to your disposal is to add extra elements that do nothing (or even better, cause errors!). No code will be provided as it is easy enough to add useless (or destructive) list elements. See program protection to get more details on destructive list elements.

Dual List method

Another thing you can do to protect saved games is to use 2 lists. Both lists will contain the same data, and can be compared to for changes made by users. To add further protection mix the order up (one list the opposite of the other).

Simple Dual List code

To get both lists the same:

:∟SAVE1→SAVE2    // make both lists the same

Checking to make sure both lists are the same:

:If not(min(∟SAVE1=∟SAVE2
:Disp "ERROR: DATA CORRUPTED

Backwards Order

To get both lists the same and into reverse order:

:seq(∟SAVE1(I),I,dim(∟SAVE1),1,-1→SAVE2

Checking to make sure both lists are the same:

:If not(min(∟SAVE1=seq(∟SAVE2(I),I,dim(∟SAVE2),1,-1
:Disp "ERROR: DATA CORRUPTED    // same as above, can change error type

CoSinTan Method

Simple, just add all the list elements except for the last one, then get sin(, cos(, or tan( of it. Then just store the result into the last element.

:sin(sum(∟SAVE,1,dim(∟SAVE)-1→∟SAVE(dim(∟SAVE

Obviously "dim(∟SAVE)" should be replaced with the dimensions of your save list, to save bytes. You can also replace sin( with any trigonometric function, such as tanh(, for added protection. Also make sure to execute a Degree or Radian command, to avoid the user being suspected for corrupting data if he's only changed a mode setting…

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/saving


Highscores

High scores typically involve saving a combination of strings (for names) and numbers (for the scores themselves) after the program is finished. The simplest high score system will only have a single score, while a complicated one might have a series of names with corresponding scores.

Managing High Scores

If there is only one high score, managing it is simple. All you have to do is check if your score is greater than the high score, and if so, change it.

:If S>∟HIGH(1
:Then
:Disp "NEW HIGH SCORE!
:S→∟HIGH(1
:End

Managing a table of multiple high scores and names would be more complicated. Here is an example routine for managing a high score table with 7 scores in ∟HIGH and 10-symbol-long names

:If max(S>∟HIGH:Then
:Disp "NEW HIGH SCORE!
:Input "YOUR NAME? ",Str1
:sub(Str1+" (9 spaces) ",1,10→Str1
:1+sum(S<∟HIGH
:sub(Str0,1,10Ans-9)+Str1+sub(Str0,10Ans-8,81-10Ans→Str0
:S→∟HIGH(8:SortD(∟HIGH
:7→dim(∟HIGH
:End

First, we should check if our score is even good enough to be in the high scores table. We're assuming that our high score table is kept in order, because we presumably initialized it that way (which will be discussed later), and we're going to keep it that way when we're done with this routine. So all we need to do is see if the score is greater than an element in our list:

If max(S>∟HIGH:Then

Next, we should input the high scorer's name. You can make this as easy or as hard as you want to, in this example I used Input for simplicity. We also pad this by appending spaces to the end then truncating the string to 10 letters, because we want it to be exactly 10 letters long.

Disp "NEW HIGH SCORE!
Input "YOUR NAME?",Str1
sub(Str1+" (9 spaces) ",1,10→Str1

Now, we find the place that the high score S got in the table. This line adds up the number of scores higher than the new one, and by adding one you get the new rank.

1+sum(S<∟HIGH

Now we insert Str1 into Str0 at the correct place. First we use sub( to find all the characters before the place we're sticking it in. Str1 is added onto this, and then we use sub( again to get all the characters that go after the new name.

sub(Str0,1,10Ans-9)+Str1+sub(Str0,10Ans-8,81-10Ans

We could do the same for lists, but there's an easier way. Since the list of scores is sorted, inserting an element into its correct place is the same as adding it to the end, then sorting the list. Finally, we remove the last score that was "bumped out" of the high score table.

S→LHIGH(8
SortA(LHIGH
7→dim(LHIGH

We're done!

End

Initializing the High Scores

Being able to add scores and names into the table would be useless without a table or names to begin with, so at the start of your program you should put in a block of code to do this.

:SetUpEditor HIGH
:If 7≠dim(∟HIGH:Then
:" (6 spaces)
:Ans+Ans
:Ans+Ans
:Ans+Ans+Ans→Str0
:0binomcdf(6,0→HIGH
:End

All SetUpEditor does is initialize the list. If ∟HIGH doesn't exist, it will create one with dimensions of 0. If the list does exist, nothing will be changed. As an extra check, you want to make sure that the list has 7 elements in it. If the list didn't already exist or didn't have 7 elements, the next block of code will execute.

Since the list not being there is a sign of the game being played for the first time, or that somebody tampered with the high scores, you should reset Str0 as well. We need Str0 to be 70 characters long for the names, but also add a space to the beginning and end for our computations when the person is ranked first or last.

Saving High Scores

We usually use a named list to store the high scores, due to the versatility of lists, and the fact that a named list probably won't get used by a different program (for more information, see Saving).

If we just have a score to deal with, it's simple to store it: just make it the first element of the list! However, with a complicated high score table, we'll have to store the names of the high scorers as well as their scores. So we have to find a way to convert a string to a list (and back).

This is simplest if you limit the variety of characters to be used for names (for example, uppercase letters and spaces). Then, you can store all the possible characters to a string, and use inString() to convert each character into a number - an index in that string. You would do this for all the characters, and append to the high scores. The following code is split up for clarity, but it could actually be combined into one line:

:" ABCDEFGHIJKLMNOPQRSTUVWXYZ
:seq(inString(Ans,sub(Str0,I,1)),I,1,70
:augment(∟HIGH,Ans→∟HIGH

Going the other way is equally simple. Unfortunately, there is no seq() command for strings, so you have to use a For loop instead, but other than that it's similar to the above code:

:" // 1 space
:For(I,8,77
:Ans+sub(" ABCDEFGHIJKLMNOPQRSTUVWXYZ",∟HIGH(I),1
:End
:Ans→Str0
:7→dim(∟HIGH

High Score Security

This is an optional side to high score saving. It's impossible to to make high scores completely tamper-proof, since someone could just look in the source code of your program and find out how you secure your high scores. However, you can use the random number generator to stop most casual cheaters (this is just one of many methods).

To do this, we first compute some number that depends on the entirety of the high score list. The most obvious is the sum of the elements. However, to obfuscate the process a bit more, you use the sum as the random number seed and save the first random number generated to the end of your list.

:sum(∟HIGH→rand
:rand→∟HIGH(78

To check if the high scores have been tampered with, you compute the sum of all the elements, and check if the first random number generated is the same as the one you saved. If it's not, somebody changed the scores, and the best way to punish the rascal is to reset them.

:sum(∟HIGH,1,77→rand
:If rand=∟HIGH(78:Then
(high scores are okay)
:Else
(the cheater has done his dirty work)
:End

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/highscores


Compression Techniques

Compression involves encoding data in an alternative format that has advantages over the un-encoded format. When determining whether to use compression, the main thing you should consider is its effectiveness (i.e., how much size and/or speed gain it results in). Of course, you need to decompress the data before you can use it again.

Graphing

One of the simplest ways of compressing data is by placing several related command values in a list, instead of listing out each individual command one after the other. A good example of this is when you are displaying a picture on the graph screen using several Pxl-On( commands. The Pxl-On( command has two arguments: an X and Y coordinate. After placing the coordinates in a list, we then just loop through the list with a For( loop:

:{10,10,25,25,50,50,60,60,35,35
:For(X,1,dim(Ans),2
:Pxl-On(Ans(X),Ans(X+1
:End

While this compression is effective, it can be improved upon. If you look at a number, it has an integer and fraction part. These two separate, but related parts can each be isolated using the iPart( and fPart( commands respectively.

Relating this back to our previous example, we should combine the two coordinates together, placing the Y coordinate as the integer and the X coordinate as the fraction. This effectively shrinks the list in half. For extracting each coordinate, you simply use the iPart( command to get the Y coordinate and multiply the fPart( command by 100 (E2) to get the X coordinate:

:{10.1,25.25,50.5,60.6,35.35
:For(X,1,dim(Ans
:Pxl-On(iPart(Ans(X)),E2fPart(Ans(X
:End

This compression technique was possible because the Pxl-On( command has two coordinates, but it would not be very effective if we were storing the Line( command's four coordinates: X1,Y1,X2,Y2. A better alternative would be to simply put all four coordinates together in the integer of the number. Probably the best example of this technique put to use is Bryan Thomas's Contra game.

The reason that this works is because a number can have up to 14 digits, so there are plenty of digits available for us to use. To extract each coordinate, you need to use a combination of iPart( and fPart(, multiplying by the related power of 10. The following code draws a line for each element in the list:

:{15231561,42133313,62186251,48604839
:For(X,1,dim(Ans
:Line(iPart(Ans(X)/ᴇ6),iPart(ᴇ2fPart(Ans(X)/ᴇ6)),iPart(ᴇ2fPart(Ans(X)/ᴇ4)),E2fPart(Ans(X)/ᴇ2
:End

(Note that the lines may not display correctly if you don't have the right graph screen coordinates, so you should set your calculator to a friendly graphing window to make all of the coordinates easily-compressible two-digit numbers. In this particular example, the graph screen coordinates are supposed to be X=0…94 and Y=0…62.)

Complex Numbers

Besides using the integer and fraction parts of a number, you can also use complex numbers. A complex number has two parts: the real part and the imaginary part. Just like how you were able to separate the integer and fraction part of a number, you can also separate the real and imaginary parts of a complex number:

:real(-5+8i   // Returns -5
:imag(-5+8i   // Returns 8

While this doesn't have much application because using the integer and fraction part of a number is generally sufficient, it can sometimes be used in place of a 2-by-n matrix; you just use a list of complex numbers, where column 1 is the real part and column 2 is the imaginary part.

Now we'll move on to a different programming situation. In games you sometimes need a switch that tells whether something is in the on or off state. It is fairly common to see beginner programmers utilize two or more variables to keep track of the switch and alternate one variable based on the other's value.

This is an ample place for not only compression but just good logical thinking. If you remember that each variable is considered a Boolean; that means the value indicates either true or false. A false value is zero while a true value is anything else. So, you just need to check to see if the value of the variable is zero:

:If not(F    // Check if the flag variable is zero

Because the F variable can be either true or false, you have the switch built-in for you. Naturally you'll want to change the value of the switch from active to inactive or vice versa, either when a certain condition happens or you have gone through the game loop or whatever, and you can do that by simply using the not operator:

:not(F→F    // Flip the value of the flag variable

Matrices

The most appropriate and needed place for compression is when storing lots of data, such as levels and maps. The most common variable used by people for storing data is matrices. This is because matrices are simple to use and they make sense since they are two-dimensional. However, matrices have one major disadvantage: size.

Instead of using matrices and wasting lots of precious space, the better approach is to use either lists or strings when storing your levels. Then when you want to use a level, you just convert it to a matrix and delete the matrix after you are done with it.

Compression via Lists

Here is a sample level stored as a list, with each element representing a row to be displayed on the home screen:

:3→dim(L1
:If L=1:Then    // If level one
:4444→L1(1
:5623→L1(2
:4567→L1(3
:End

Using the iPart( and fPart( commands that we discussed previously, you can break apart each number into its own separate integer and fraction elements. This allows us to then store each number into a specific position in the matrix, looping through it with a couple For loops:

:{3,4→dim([B]
:For(Y,1,3
:L1(Y→Z
:For(X,1,4
:iPart(10fPart(Z/10^X→[B](Y,5-X
:End:End

Compression via Strings

The formula for storing a level as a string and converting it to a matrix is not much different than it was for the list:

:If L=1:Then    // If level 1
:"444456234567→Str1
:End
:1→F
:{3,4→dim([A]
:For(A,1,length(Str1
:exp(sub(Str1,A,1→[A]((fPart(A/4)!=0)+iPart(A/4),F
:F(F<4)+(F<4)+(F=4→F
:End

While this probably seems like a waste to go through all of this work just to compress a level, it is very important when you have lots of level that you want to store. In addition, the calculator only has a limited amount of memory to begin with, so you need to take advantage of every opportunity to save memory.

Single Digit Numbers

We can compress a list of up to 14 elements into a single integer whose digits are the elements in reverse. Say you had this 8-element list stored in L₁:

{7,0,3,4,1,6,6,2}

Then to compress, use this.

.1sum(L₁10^(cumSum(1 or L₁

Remember, 10^( is [2ND] then [LOG], not [1][0][^][(].

You should get this:

26614307

You'll notice that the digits are in reverse. That might be a bit confusing, but having it in reverse makes it smaller and faster.

So now, we decompress:

int(10fPart(Ans/10^(seq(Z,Z,1,8

In general, replace 8 with the dimension of your list, or log(Ans if the number of digits is unknown.

There you go. It is decompressed back into Ans. So, now we can compress single-digit data. But what about double-digits?

Double Digit Numbers

Double digits are a little more complicated, but they are also more useful because they allow up to 100 different positive integers instead of just 10.

Several methods were mentioned previously for decompressing 2-digit numbers, if you paid attention.

So, on to compressing! Say you had this 4-element list stored in L₁:

{24,47,36,42}

To compress it:

.01sum(L₁10^(2cumSum(1 or L₁

The answer:

42364724

The decompression:

int(E2fPart(Ans/10^(2seq(Z,Z,1,4

Multiple digits of any length

It is a little harder to compress multiple digit of any length into one number, so more code is needed to accomplish this.
This method prompts the user for how many values should be entered and then prompts for each individual values. For the current version of this code, you must enter the values with zeroes in front if they are not of the maximum length. To change the maximum length, alter any occurrence of 10^(4) to e.g. 10^(5) for numbers of the length 5.

Example:
If I want to input 3 numbers of the length 4. I would enter:
3 // How many values I want to enter
001
075
254

That would then compress those numbers into a single number.

This code will not work if the resulting compressed number is longer than 14 digits long (the maximum calculator precision).

Key:
A = compressed number
N = how many values you want to input
V = a new value to be processed
// = Denotes a comment in the code, shouldn't be included in your programs
-> = Denotes the STO command

0->A
Prompt N
For(B,1,N)
Prompt V
A/10^(4)->A
A+(V/10^(4))->A
If B=N:A+B->A
End

Disp A

// We are now decompressing A into L1
iPart(A)->N
A-N->A
N->dim(L1)
For(B,1,N)
A*10^(4)->A
iPart(A)->L1(B)
A-L1(B)->A
End

//Displaying the decompressed number in the form of a list
Disp seq(L1(Z),Z,1,dim(L1),1)

I am currently trying to make this more friendly to programs that would possibly be able to use this within their own code.

References

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/compression


Making Maps

For many games, the gameplay consists of going through all of the maps in the game. For example, in a maze game where each map is a different maze, when you get through the first maze you go on to the second maze, and so on until you finish all of the mazes. Another common example is an RPG where the player can move their character around on the screen, and each screen is part of a larger map.

How to Store Maps

In order to keep track of all of the different things in a map, it obviously requires that you store the map to a variable. There are three different variables that you can use to store maps, and they each have their own advantages and disadvantages:

  • Matrices — Matrices are best used for two-dimensional data, and are easier to access and manage than both lists and strings. At the same time, matrices are the largest variable, which can be important if you are trying to keep your program as small as possible.
  • Lists — Lists are best used for one-dimensional data, and are faster to access than both matrices and strings. Lists also have the additional advantage that you can create your own custom lists, which decreases the likelihood that they will get messed with.
  • Strings — Strings can be adapted for basically any context, and they are smaller in size than both matrices and lists. In addition, unlike matrices and lists which have a set maximum size (99x99 and 999 respectively), strings can be as big as RAM will allow.

Generally speaking, it's best to use the most appropriate variable for the application. Going back to the maze game, for example, a matrix would probably be the preferred variable to use because a maze has a two-dimensional shape to it.

When storing a map in a variable, you have to assign numbers to represent the different things in the map: an empty space might be zero (0), a wall might be one (1), and the player might be two (2). You would then check for these numbers when determining what to do on the map or what to allow (such as movement by the player).

Here is an example of a simple 8x16 map stored in each of three different variables (note: the respective variable is all on one line, it's just split up to make it easier to read):

:[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
 [1,2,1,0,0,0,1,0,0,0,1,0,0,0,1,1]
 [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1]
 [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1]
 [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1]
 [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1]
 [1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0]
 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1→[A]
:{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
 ,1,2,1,0,0,0,1,0,0,0,1,0,0,0,1,1,
 ,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,
 ,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,
 ,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,
 ,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,
 ,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,
 ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1→L₁
:"1111111111111111
 1210001000100011
 1010101010101011
 1010101010101011
 1010101010101011
 1010101010101011
 1000100010001000
 1111111111111111→Str1

As you can see, the string map is the smallest of the three variables because you don't have to add all of the additional characters (the braces and the commas) like you do with the matrix and list. (You can actually get around this problem by storing your maps as a string, and then converting them to a matrix or list when you need to use them.)

How to Display Maps

Once you have your map stored in one of the variables, the next thing to do is to display it on the screen. The calculator has two different screens for displaying things — the home screen and the graph screen. The home screen is generally reserved for text, while the graph screen is generally reserved for graphics.

On the Home Screen

When displaying a map on the home screen, you use the Output( command together with a For( loop. You also need to decide what you want to display for the different things in the map. The easiest option is to just display the literal values stored in the map (i.e., 0, 1, 2, 3, etc.). A better option, although it's a little more complex, is to display a character that is representative of what the value stands for.

For example, in our maze map, we had spaces (0), walls (1), and the player (2). The spaces are what the player is going to be able to move on, so they naturally should not be displayed on the screen. A wall, on the other hand, is something that the player cannot move through, so it should be displayed on the screen. A good choice for a wall character is a 1 or an uppercase X. The player is what the user is in control of, so you want it to stand out. A good choice for a player character is an S or uppercase O.

Besides deciding what character you will use for each type of thing in a map, you also need to have a check for each one when displaying the characters. The most straightforward way to do this would be to have a separate If conditional that goes with each type of character. A better way to do this, however, is to put all of the characters in a string, and use the sub( command to access the appropriate character. For example, here is how you would display the maze from before:

:For(Y,1,8
:For(X,1,16
:Output(Y,X,sub(" XO",1+[A](Y,X),1
:End:End

As you can see, we decided to use an X for the walls and an O for the player. The other important thing to notice is that we used two nested For( loops to display the map. Since the maze is two-dimensional, two For( loops are needed: the first loop gets the Y-coordinates and the second loop gets the X-coordinates. Inside the second For( loop is where we access the respective (Y,X) coordinate of the matrix and display it using Output(.

Displaying a maze level stored in a list or string is very similar, but it requires you to use a simple formula to convert the respective coordinates on the screen: X+16(Y-1). For the string, you also need to use the sub( command to access the individual character in the string, and the expr( command to convert it to a number.

:Output(Y,X,sub(" XO",1+L₁(X+16(Y-1)),1
:Output(Y,X,sub(" XO",1+expr(sub(Str1,X+16(Y-1),1)),1

Where this formula comes from is that each row on the home screen is 16 characters wide, and the first row you just access the X coordinate by itself (i.e., when Y is 1, Y-1=0, and subsequently 16*0=0). If you create a similar map on the graph screen, you need to modify this formula to match the number of characters per row on the graph screen and to take into account that the graph screen coordinates start at zero.

Besides using the formula, the string can also be displayed one other way. The Output( command will wrap any text that goes over the 16 characters of a row to the next row (and likewise with that row), and subsequently you can use a single command to display the entire map across the whole screen.

Since every space is overwritten with the map, this does not require a ClrHome command to clear previously displayed characters. Unfortunately, there is no equivalent for the graph screen.

On the Graph Screen

Displaying a map on the graph screen is essentially the same as displaying a map on the home screen, except you can make the map much more detailed because the graph screen can be manipulated on a pixel level. There are several graphics commands available:

When displaying a particular part of the map, you can use a combination of these commands to create almost anything you want, whether it is a wall, a monster, a rock, or even a smiley face. For example, using our 8x16 maze level from before, instead of outputting the X character for the wall in the matrix, we can draw a wall using lines:

:For(Y,1,8
:For(X,1,16
:If 1=[A](Y,X:Then
:Line(4X-2,57-6Y,4X-2,53-6Y
:Line(4X-3,57-6Y,4X-3,53-6Y
:End:End:End

You should note that the window dimensions need to be X=0…94 and Y=0…62 for this example to show up correctly. In fact, with exception to the Pxl- and Text( commands, all of the graphics commands are dependent upon the window dimensions, so you should always use a friendly graphing window to ensure everything shows up as you intended.

There are several other ways to create graphics, and you should check out the graphics page for more information.

Where to Store Maps

After deciding on how you will store and display your maps, you then need to determine where you will store the maps: in the program itself or in a subprogram (or subprograms). When deciding which route to go, you need to think about how many maps you plan on having. If there aren't many maps (i.e., ten or less), they should usually all be stored in the program itself.

In the Program

For storing the maps in a program, you place each map inside its own If conditional and list the maps one after another. You then check to see which map the player needs and set up the variables for that map. Each map might also have some related information that goes along with it, such as the number of coins the player has to collect or the number of lives, so you would need to use an If-Then conditional instead:

:If A=1:Then  // Check if the player is at map 1
:{1,2,0,0,0,1,5,5,7,3,4,2,9,8,7,1→L₁
:3→B:4→C
:End

Once you have your maps stored in their individual conditionals, the next thing to do is decide where you you want to store them in the program. An obvious choice is just placing them right at the beginning of the program. In order to do this, however, it requires that you be able to access them. This normally entails placing a label before the maps, and then using a Goto to jump to them.

An important consideration when placing maps at the beginning of a program is what values you use for the If conditional variable. While you could use something simple like one or two, those values have a high probability of being accidentally entered in by the user or being set by another unrelated program, which would cause your program to store the respective map. What works better is to use random decimals (like .193 or 1.857) or math symbols (like e or π).

In a Subprogram

If there are several maps, you might want to consider placing them in a separate subprogram. The main reason is that when the maps are stored in the program, the program has to go through all of the code before the maps to reach a particular map. Depending on the size of the program, this can make for some major slowdowns in between maps. The internal maps also slow down the main program code itself.

Related to the first reason, the second reason to consider using a separate subprogram is that changing the maps is much easier in a subprogram. Instead of having to go through the entire program, looking for the map to change, you can just focus on one map at a time. This makes the maps more manageable, and also prevents you from accidentally changing other parts of the program.

The program code for the maps basically remains the same, it's just in another program. You might notice, though, that if you have lots of maps it takes a while for program execution to go back to the main program. This happens because program execution doesn't return to the main program until after it reaches the end of the program. You can fix this problem by placing the Return command at the end of each map conditional:

:If C=3:Then
:[[0,1,0][2,1,2][1,2,0→[B]
:3→A:3→B
:Return  // Stop program execution and return to main program
:End

Now that the maps are in a separate subprogram, you need a way to access them. When you want to access a map, you set the respective variable to the value of the map that you want, and then call the subprogram from the main program using the prgm command and the subprogram name:

:2→A
:prgmGAMELVLS

Unfortunately, storing the maps in a subprogram does have one major disadvantage. The user now needs another program to use the main program. If somebody tries to run the program and they don't have the maps subprogram, the main program will not work properly, and will actually return an ERR:UNDEFINED error when the program tries to call the non-existent maps subprogram. Even if this isn't your fault, the result is that your program looks very sub par.

Because of this problem, doing an all or nothing map separation (i.e., all of the maps are either stored in the program or in a separate subprogram) is usually a bad idea. The better alternative is to split up the maps so that the first ten maps (or so) are stored in the program, and the rest are stored in the subprogram. The user will now at least have some built-in maps to play, regardless of if they have the maps subprogram. The user simply won't have knowledge of the other maps available for them to play.

Sample Map-Based Game

This is a sample map-based game and the objective in each level is to get the "+" (plus sign), which causes you to advance to the next level. The game is played on the home screen using the arrow keys to move and CLEAR to quit. The maps are stored as lists in a separate program, along with the starting coordinates for your character.

(NOTE: Each list is all on one line, it's just split up to make it easier to read.)

PRGM:MAZELVLS
:If not(A:Then
:{1,2,1,1,1,1,2,2,1,1,1,1,1,1,1,1,
1,2,1,2,2,1,2,2,1,2,2,2,2,2,2,1,
1,2,1,2,2,1,2,2,1,2,1,1,1,1,1,1,
1,2,1,2,2,1,1,1,1,2,1,2,2,2,2,2,
1,2,1,2,2,2,2,2,2,1,1,2,2,1,1,1,
1,2,1,1,1,1,1,1,2,1,2,2,2,1,2,1,
1,2,2,2,2,2,2,1,2,1,2,2,2,1,2,1,
1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,3→L1
:1→Y:1→X
:Return
:End
:If A=1:Then
:{1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,
1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,
1,2,1,2,3,2,2,2,2,2,2,2,2,1,2,1,
1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,
1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,
1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1→L1
:8→Y:16→X
:Return
:End
:If A=2:Then
:{1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,3,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,
1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2→L1
:1→Y:1→X
:End
PRGM:MAZE
:For(A,0,2
:prgmMAZELVLS
:" // 1 space
:For(I,1,dim(L1
:Ans+sub(" =+",L1(I),1
:End
:ClrHome
:Output(1,1,sub(Ans,2,dim(L1
:Repeat 3=L1(Ans+16Y-16
:Output(Y,X,"X
:Repeat Ans
:getKey→K
:End
:If Ans=45:Goto Q
:Output(Y,X," // 1 space
:min(16,max(1,X+sum(ΔList(Ans={24,26→C
:min(8,max(1,Y+sum(ΔList(K={25,34
:If 2≠L1(C+16Ans-16:Then
:Ans→Y:C→X
:End:End:End
:Lbl Q
:DelVar L1
:ClrHome
:"Lost
:If A=3
:"Winner

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/maps


Movement in Maps

Movement is commonly used in programs as a way to add user interaction. It is part of user input as it relies exclusively upon the getKey command to work. You can use movement in many programs and for many different things, including moving a cursor in a menu or moving a character around the screen. It is the latter case that we are going to explain and show here.

The Code

Homescreen

This is the basis for the code used in the two later examples. An explanation for why it works can be seen here.

:4→A
:8→B
:Repeat K=21
:getKey→K
:If Ans
:Output(A,B," // 1 space
:min(8,max(1,A+sum(Δlist(Ans={25,34→A
:min(16,max(1,B+sum(Δlist(K={24,26→B
:Output(A,Ans,"X
:End

Graphscreen

This is the same code as the first, but it has the graphscreen initialization process at the beginning, and you have to switch up the keypress codes.

:Zstandard
:104→Xmax
:72→Ymax
:Zinteger
:1→A
:1→B
:Repeat K=21
:getKey→K
:line(A,B,A,B,not(K
:min(94,max(0,A+sum(Δlist(K={24,26→A
:min(62,max(0,B+sum(Δlist(K={34,25→B
:End

Depending on what is being moved, the code might need to be revised. This particular code will move a pixel, or you can make it a line if you want. However, to move sprites, you will need to add to the coordinate variables instead. If you are moving a group of pixels, it would be ideal to hard code it.

Simultaneous Movement

Once you have learned how to create simple movement, the next natural step is to add some enhancement to make it more complex. One of the most common things desired is simultaneous movement — moving multiple things at the same time. Unfortunately, real simultaneous movement isn't really possible because of the limitations of the calculator, but you can emulate it.

When moving things, you need to be able to keep track of their position on the screen and the number of things. While the fastest way would be to use individual real variables for each thing, the best approach in terms of speed and size is a list and real variable respectively.

Before you initialize the list, it is good to consider how many things you want to allow on the screen at any one time. This is an important consideration because the more things you need to keep track of, the slower the program runs. A good range to shoot for is 5-15.

Here is what the code looks like so far:

:DelVar ADelVar L110→dim(L1

We are using the A real variable as the counter and the L1 list variable to keep track of the 10 object positions on the screen. We chose to initialize the list elements to 0 because that is our flag to determine if the object is active or not.

Now when you want to add another object, you simply need to increment the counter and then store the object's position on the screen to the list. You also need to remember to check that you haven't exceed the maximum number of allowed objects on the screen. You can combine the X and Y screen coordinates together into one list element using compression.

:A+1→A
:If A<11
:YE2+X→L1(A

You also need to check for when a thing goes off the screen. When this happens, you first look at the counter to make sure it isn't at 0, and then loop through the thing positions and move all the things to the previous list element. You then decrement the counter.

:If A>1:Then
:For(X,1,A-1
:L1(X+1→L1(X
:End
:A-1→A
:End

When moving these things, you simply loop through the positions list and then change the position of whatever thing you want. You basically are moving one thing at a time and then switching to the next thing once it is done.

Collision detection

If you want to restrict your character's movement so that it doesn't move through solid spaces such as walls, you will need some sort of collision detection. Since this example is on the home screen, the best method is to use a string. Create a string with 128 elements, leaving spaces for nothing, which will be represented as zeros for visual aid. Equal and unequal signs make good walls. Here is an example, a maze. For more info maps, go to the page making maps

:"================
  =000=000=000=0==
  =0=0=0=0=0=0=0==
  =0=0=0=0=0=0=0==
  =0=0=0=0=0=0=0==
  =0=0=0=0=0=0=0==
  =0=000=000=000==
  ================→Str1

Notice how the "maze" is set up so that the outer boundaries are all walls. The advantage of this is that it allows us to save space and speed on the calculator by removing the specific boundary check. The disadvantage is that it limits the amount of characters on screen to 6x14 instead of the full 8x16.

Now we can add the collision detection code in with our original movement code. You should notice that the main difference is the player's position for movement is checked to determine if the player is going to move onto an equals sign.

Notice how there is an extra argument after the Repeat. This allows us to have the character switch to the next maze when it reaches the end. You could also use this to switch to another map at the screen's edge.

:ClrHome
:4→A:8→B
:"================
  =000=000=000=0==
  =0=0=0=0=0=0=0==
  =0=0=0=0=0=0=0==
  =0=0=0=0=0=0=0==
  =0=0=0=0=0=0=0==
  =0=000=000=000==
  ================→Str1   //remember, 0's are spaces
:Output(1,1,Ans
:Repeat K=21 and AB=26   //AB=26 can be changed for different exit point
:getKey→K
:If Ans
:Output(A,B,"_  //One space, checks for key press and erases
:sum(Δlist(Ans={25,34
:A+Ans(" "=sub(Str1,16(A-1+Ans)+B,1→A   //If future coordinate is a space, it moves
:sum(Δlist(K={24,26
:B+Ans(" "=sub(Str1,16A-16+B+Ans,1→B
:Output(A,Ans,"X
:End
:"     //second maze

And you can repeat this until all your mazes have run through. In addition to using strings, you can also use lists, matrices, or hardcode the whole map in if statements. The code is fundamentally the same, except there is a different formula used to display the map on the screen and you also check the available spot with that formula. Again, just try to understand the code and play around with it.

On the graph screen, you cannot make a string for collision detection. Otherwise, you would be looking at a 5828 character string! Instead, on the graph screen, you can use a command called pxl-Test( to tell you what is in the next space being moved to.

The pxl-Test( command finds the status of a pixel on the graph screen returning a 1 if the pixel is on or a 0 if the pixel is off. Therefore, if you get a 1, the character shouldn't move to the next space. If the pxl-Test( is 0, then the character moves to the next space. The following code is the base of how this works, and you can alter it to add boundary checks or advanced sprite manipulation.

:sum(Δlist(K={25,34
:A+Ansnot(pxl-Test(A+Ans,B→A

References

  • Kerm Martian and his post at the UTI TI-Basic forum about keeping track of multiple shots.
  • darkstone knight's post which led to the latest few updates in the formulas.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/movement


Custom Text Input

Custom text input is used when you want to get input on the graph screen (or the home screen, if you don't like the look of Input or Prompt). As the Input and Prompt commands only work on the home screen, the only option available is to make your own text input routine.

The Basic Routine

The core of the text input routine is using the getKey command together with a string of acceptable characters organized to follow the order of the respective key codes, and then extracting one substring character and storing it to the outputted text string:

:" →Str1  // 1 space
:Repeat K=105
:Repeat Ans>40 and Ans<94 or Ans=105
:getKey→K
:End
:Ans-20-5int(.1Ans
:If 25>length(Str1) and 0<Ans and Ans<29
:Then
:Str1+sub("ABC  DEFGHIJKLMNOPQRSTUVWXYZ",Ans,1→Str1
:Text(10,1,Str1
:End
:End
:If 1<length(Str1
:sub(Str1,2,length(Str1)-1→Str1   //removes initial space

If that sounds confusing, please let me break it down for you. We first need to initialize the string variable that we will be using to hold the text the user inputs. You can use whichever one of the ten string variables (Str0-Str9) you want. The reason we initialize the string with a single character is because the calculator returns an error if you have a null string.

:" →Str1

We now begin the main program loop. The program will loop until the user presses ENTER. After that, we loop until the user presses a letter key (as all letters are assigned key codes from 41 to 93) or ENTER.

:Repeat K=105
:Repeat Ans>40 and Ans<94 or Ans=105
:getKey→K
:End

After the user has pressed one of the necessary keys, we then need to take the respective action in the program. If the user pressed one of the letters of the alphabet, we first check to see that the string is not already at the end of the screen (i.e. its length is 25). If it is less than 25, we add that text to our string variable and display the whole string:

:Ans-20-5int(.1Ans
:If 25>length(Str1) and 0<Ans and Ans<29
:Then
:Str1+sub("ABC  DEFGHIJKLMNOPQRSTUVWXYZ",Ans,1→Str1
:Text(10,1,Str1
:End

We finally close the main program loop. This text input routine just has basic functionality, as it was designed to show you how to do custom text input. It's up to you whether you want to extend it to include a larger range of acceptable characters, word wrapping, or whatever feature you want to include.

Tweaking the Routine

These are advanced features for a custom text input routine.

Backspace functionality

The above routine is very limited: once we type something in, we can't go back and change it. This add-on allows the user to press the DEL (delete) key to delete the last letter typed. To add this functionality, change the first loop code from ":Repeat Ans>40 and Ans<94 or Ans=105" to ":Repeat Ans>40 and Ans<94 or max(Ans={105,23", and add the following code right before the final End that terminates the outer loop.

If the user pressed the DEL key, we first check that the string variable has at least one character already in it (so an error isn't returned), and then remove the last character at the end of the string and redisplay the string (erasing the three spaces to the right of the last character left behind from the deleted character):

:If K=23 and 1<length(Str1 //if DEL pressed and some letters have been entered
:Then
:sub(Str1,1,length(Str1)-1→Str1
:Text(10,1,Str1,"   //three spaces after the "
:End

Flashing Cursor

A flashing cursor makes it clear that you mean business, or that you mean for the user to type in text. The code for a flashing cursor should replace the ':getKey→K' in the basic routine. You must also replace 'Ans' in ':Repeat Ans>40 and Ans<94 or max(Ans={105,23' with 'K'. 'K' must also be added onto a new line after the second 'End' after the code below. This is because the new variable 'I' messes with 'Ans'.

We start the routine normally: repeat until a key is pressed. The two Text( statements will draw a [ then erase its two tails, effectively drawing a horizontal bar. The For( loop creates an artificial delay between drawing and erasing the cursor. However, we want to end the loop if a key is pressed (so we don't have to wait until the cursor finishes flashing to type in a key). That's what the I+5Ans→I statement does: if K isn't 0, it will make I greater than 30, which will end the loop. We want to erase the cursor if a key was pressed or if I=16 (halfway through the delay loop). Finally, we end both loops.

:Text(10,4length(Str1)-2,"[
:Text(10,4length(Str1)-1," //1 space after the quote
:For(I,1,30
:getKey→K
:I+5Ans→I //if K isn't 0, I will go out of bounds, ending the loop.
:If I=16 or K
:Text(10,4length(Str1)-2," //1 space after the quote
:End

Adding Number Functionality

Although this routine differs from the one above, it accomplishes the same thing. Again, thanks to DarkerLine for the keypress to letter formula. Harrierfalcon came up with the formula to convert keypresses to numbers.

:ClrDraw
:DelVar A15→B
:Text(1,82,"             
:Text(0,82," LET
:" →Str1
:Repeat max(M={45,105,21
:‾5→C
:Repeat M=23 or max(Ans={21,45,105}) or (not(A)M>40 and not(A)M<95 and M≠44) or max(AAns={92,93,94,102,82,83,84,72,73,74
:C+1-10(C>4→C
:Text(29,B,sub(" [",1+(Ans>0),1
:Text(29,B+1," 
:If M=31
:Then
:not(A→A
:Text(0,83,sub("LETNUM",3A+1,3
:End
:getKey→M
:End
:If min(M≠{21,105,45,23
:Then
:If A
:Then
:sub("0123456789",27-3int(.1M)+10fPart(.1M)+2(M=102),1
:Text(29,B,Ans
:Str1+Ans→Str1
:B+4→B
:Else
:sub("ABC  DEFGHIJKLMNOPQRSTUVWXYZθ",M-5int(.1M)-20,1
:Text(29,B,Ans
:Str1+Ans→Str1
:B+4→B
:End
:Else
:If M=23 and 1<length(Str1
:Then
:B-4→B
:Text(29,Ans,"      
:sub(Str1,1,length(Str1)-1→Str1
:End
:End
:End

A=1 if NumLock is enabled, and A=0 if AlphaLock is enabled. Allow me to break it down.
:ClrDraw
:DelVar A15→B
:Text(1,82,"             
:Text(0,82," LET
:" →Str1

I'll let you guess on this one.
:Repeat max(M={45,105,21
:‾5→C

This resets the cursor counter, and initializes the loop that won't quit until [ENTER],[2ND], or [CLEAR] is hit.
:Repeat max(Ans={23,21,45,105}) or (not(A)M>40 and not(A)M<95 and M≠44) or max(AAns={92,93,94,102,82,83,84,72,73,74

This initializes the loop which won't quit until proper keys other than [ENTER], [2ND], [CLEAR], or [DEL] is hit.
The second boolean value is structured so that if A=0, it means AlphaLock is enabled, and if a letter key is pressed, then it will exit the loop. If A=1, then it won't work, because not(A)M will equate to 0 every time. If [VARS] is pressed, nothing happens, because there is no letter there.
The second Boolean value was created in a fashion that tells if A=1, then M is left alone. If it is not, then it doesn't count.
:C+1-10(C>4→C
:Text(29,B,sub(" [",1+(Ans>0),1
:Text(29,B+1," 
:If M=31
:Then
:not(A→A
:Text(0,83,sub("LETNUM",3A+1,3
:End
:getKey→M
:End

The first line increments C, and returns it to -5 if C=5.
The second line outputs [ or a space, if C<= 0 or C>0, respectively.
The third line clears the bracket's tails, or does nothing.
Lines 4-8 toggles AlphaLock and NumLock, and updates the display.
:If min(M≠{21,105,45,23
:Then
:If A
:Then
:sub("0123456789",27-3int(.1M)+10fPart(.1M)+2(M=102),1
:Text(29,B,Ans
:Str1+Ans→Str1
:B+4→B
:Else

This If-Then is executed only if [2ND],[DEL],[ENTER], and [CLEAR] were NOT pressed. This prevents garbled numbers with would cause ERR:DOMAIN. This is executed only if NumLock was on.
:Else
:sub("ABC  DEFGHIJKLMNOPQRSTUVWXYZθ",M-5int(.1M)-20,1
:Text(29,B,Ans
:Str1+Ans→Str1
:B+4→B
:End

This is executed if NumLock was NOT on, i.e. if AlphaLock was on.
The rest shouldn't have to be explained. Optimizations are out there…can you find them?

Advanced Editing Functionality

This routine adds several features that are not in the other versions. It allows for uppercase and lowercase text with switching in between them. It allows the user to move the cursor throughout the text and insert text and delete text where ever they would like. The user can also clear the current text and start over. Unfortunately, the code is a little hard to decipher, but we'll work through it. The main deficit of this program is that it is incompatible with the TI-83. This can be remedied, as explained below.

:"ABC  abc  DEFGHdefghIJKLMijklmNOPQRnopqrSTUVWstuvwXYZ(Theta)!xyz(Theta).  :?   :? →Str0
:"  →Str1   // 2 spaces in quotes
:DelVar M1→P
:Repeat K=105 and 2<length(Str1
:Text(0,0,sub(Str1,1,length(Str1)-P)+"|"+sub(Str1,length(Str1)-P+1,P)+"        // 5 spaces after quote
:Repeat Ans
:getKey→K:End
:P-(K=26 and Z>1)+(K=24 and Z<length(Str1)-1→P
:M xor K=31→M
:If K>40 and K<105 and K≠44 and K≠45
:sub(Str1,1,length(Str1)-P)+sub(Str0,K-40+5M,1)+sub(Str1,length(Str1)-P+1,P→Str1
:If K=23 and P<length(Str1)-1
:sub(Str1,1,length(Str1)-P-1)+sub(Str1,length(Str1)-P+1,P→Str1
:If K=45:Then
:"  →Str1   // 2 spaces in quotes
:1→P
:End
:End
:sub(Str1,2,length(Str1)-2→Str1

The first three lines take care of variable initialization. M stores whether capitals are enabled or not. M = 0 if its uppercase, M = 1 lowercase. Str0 contains all the uppercase and lowercase letters, including information for the last row of keys on the calculator. Str1 is the string that the text will be stored in. The information will be between the two space characters so that we can insert information at the beginning and end without having problems. P is the number of places before the end of the string to place the cursor. This is the most crucial variable, this will allow for the painless insertion of text and deleting of text anywhere in the string.
TI-83 Compatibility: Change Str0 to be the string listed above for the basic routine ("ABC DEFGHIJ…."). This, along with the other change listed below, will make this TI-83 compatible.
:Repeat K=105 and 2<length(Str1

This repeats until [ENTER] is pressed and makes sure that text has been entered into the string before exiting.
:Text(0,0,sub(Str1,1,length(Str1)-P)+"|"+sub(Str1,length(Str1)-P+1,P)+"        // 5 spaces after quote

This displays the text at 0,0 on the graph screen. This is a difficult line so let's break down what is being outputted onto the screen.
sub(Str1,1,length(Str1)-P)+"|"+

This returns all the characters that are before the cursor and then outputs the cursor
sub(Str1,length(Str1)-P+1,P)+"        // 5 spaces after quote

This returns all the characters that are after the cursor and then outputs some spaces. The spaces are there because when delete is pressed, the string will get smaller, and some characters will be left over. This is to cover those characters up.
The next two lines just get the key press and store it into the variable K.
:P-(K=26 and Z>1)+(K=24 and Z<length(Str1)-1→P
:M xor K=31→M

The first of these two lines control the movement of the cursor (stored in P). If the right arrow is pressed then P will decrement, less spaces from the end of the string. If the left arrow is pressed then P will increment, more spaces from the end of the string. The other conditions make sure that the cursor doesn't go too far in either direction.
The second of these lines controls the current capitalization state. By using the xor command, M will switch back and forth between 1 and 0 (lowercase and uppercase, respectively) every time the [ALPHA] key is pressed.
:If K>40 and K<105 and K≠44 and K≠45
:sub(Str1,1,length(Str1)-P)+sub(Str0,K-40+5M,1)+sub(Str1,length(Str1)-P+1,P→Str1

These lines test to see if the key press is a letter key and then inserts the letter into the string. The second line concatenates three strings together. The first is all the characters before the cursor. The second is the letter that was pressed (found in Str0). The third is all the characters after the cursor. This is all stored back into Str1.
TI-83 Compatibility: In order to make this compatible with the TI-83, change the middle string that is concatenated to sub(Str0,K-20-5int(.1K),1). This, along with the other change, listed above will make this TI-83 compatible.
:If K=23 and P<length(Str1)-1
:sub(Str1,1,length(Str1)-P-1)+sub(Str1,length(Str1)-P+1,P→Str1

These lines test to see if [DEL] was pressed and then deletes a character from the string. Since the character deleted is from behind the location of the cursor, the conditional tests to see if the cursor is at the beginning of the text (where there is no character before the cursor). The second line concatenates two strings together. The first is all the characters before the cursor minus the last one (the character being deleted). The second is all the characters after the cursor. This is all stored back into Str1.
:If K=45:Then
:"  →Str1   // 2 spaces in quotes
:1→P
:End

These lines test to see whether [CLEAR] was pressed and then clears the text accordingly. Both Str1 and the location of the cursor are reset to their original values.
After this line, the main loop ends.
:sub(Str1,2,length(Str1)-2→Str1

This line removes the extra space on each end of the string and returns Str1.

If you want to let the user view the current capitalization state, add the following line before the getKey loop.

:Text(55,90,sub("Aa",M+1,1

The coordinates can obviously be changed to place this anywhere around the graph screen.

References

  • DarkerLine came up with the formula for translating the letter keys into the short string.
  • Harrierfalcon created the formula to convert number keypresses into a short string.
  • Zaphod Beeblebrox created the advanced editing functionality routine.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/custominput


Graphics

There is only so much that can be shown with text alone: sooner or later, any kind of program, whether it is a game or a complicated math tool, will have to use graphics. The purpose of this page is to describe the various methods of rendering graphics, along with their advantages and disadvantages. In many cases, you'll find that no one method suits your needs perfectly, and they will need to be combined to produce something that looks good without sacrificing too much speed or memory space.

Picture Variables

The simplest and fastest way to display just about any image is to save it in a picture variable beforehand, and then use the RecallPic command to instantly display it to the screen. There is no choice in positioning the picture, or displaying anything smaller than the entire screen, so this method is mostly limited to title screens.

The main advantages of this method are:

  • The speed — no other TI-Basic instruction can fill the screen as quickly.
  • The image can be made as complex as desired, without loss of performance.

However, there are numerous drawbacks:

  • Each picture variable uses 767 bytes of precious memory.
  • Furthermore, the picture is stored outside the program, where it can be overwritten.
  • There are only 10 picture variables to be shared between all TI-Basic programs.
  • The picture is static and can't be moved around the screen easily.

There are several ways to get around this problem. A decent solution is to use groups to keep the program and its pictures together and backed up — this ensures that even if a picture is overwritten, that this will not be permanent. Another possibility is to hope that there won't be any other conflicting programs to cause problems.

An example of picture variables at their best is the title screen in Contra: the image is too complicated to reproduce easily in any other way, and the result has become iconic of the game.

Hard-coded Sprites

Hard-coded sprites are, in a sense, the other extreme to go to. The idea is to write out the specific commands (usually, ones like Pt-On( or Pxl-On( to display an image. A friendly window might be useful. Here is an example, drawing a smiley face near the coordinate (X,Y):

:Pt-On(X,Y,2)
:Pt-On(X+2,Y,2)
:Pt-On(X,Y-2,2)
:Pt-On(X+2,Y-2,2)
:Pt-Off(X+1,Y-2)

Unless the image only needs to be drawn at one point, adding variables such as X and Y above is useful, allowing the same code to draw the same thing at multiple locations. It should also be noted that the Pt-On( and Pt-Off( commands have an optional third argument that allows you to draw a 3x3 box or cross (using 2 or 3, respectively), which is smaller and faster than the individual composite commands.

The advantages of this approach are:

  • It is very flexible: no matter the image, it can be drawn with some amount of commands.
  • It is still fairly fast, although slower than RecallPic.
  • It's easy to make a sprite that moves around on the screen.

The drawbacks, on the other hand, are:

  • Of all the methods on this page, this one uses the most memory.
  • The more complex the image, the more commands it will require to draw.
  • Every different image requires its own instructions, complicating program logic.
  • It's easy to make a mistake or typo, and hard to fix one.

A good use for hard-coded sprites is a fancy cursor in a menu: these are usually small and relatively simple, don't require many different images, and play to the strengths of hard-coded sprites. You can also combine hard-coded sprites with compression to reduce the number of graphic commands needed, although it often causes a hit to the program speed.

Plot Sprites

A somewhat different idea for rendering graphics, plot sprites use the Plot#( commands to draw multiple points or multiple lines very quickly (taking a shortcut, so to speak, to the approach above). In this case, all of the information to draw the sprite (that is, the coordinates of the points or lines) is stored in a pair of lists. Since plots use point coordinates, a friendly window may be useful.

To display a sprite, first store the coordinates to two lists (this article will assume they are L1 and L2). Next, set up the plot variable with Plot#(Scatter,L1,L2) (to draw points at the coordinates) or Plot#(xyLine,L1,L2) (to connect the coordinates with lines). Then, the DispGraph command will update the graph screen with all the plots that are currently in use. There are three plots available, which can be switched on and off with the PlotsOn and PlotsOff commands.

Here is an example of the same image displayed using plot sprites:

:{4,0,0,4,4,4,0,2,2}→L1
:{0,0,4,4,0,2,2,2,4}→L2
:Plot1(xyLine,L1,L2
:DispGraph

Plot sprites are uniquely suited to being moved around the screen: once the setup phase is done, just modify the lists slightly and then use DispGraph again to draw the sprite at a different location, erasing it from where it was. Just using simple arithmetic on the lists lets you move, reflect, rotate, and stretch a sprite. The table below shows the formulas required (some intuitive, some not):

Transformation Formula
Horizontal translation A+L1→L1
Vertical translation B+L2→L2
Reflection about the x-axis -L1→L1
Reflection about the y-axis -L2→L2
Rotation 90°
clockwise
L1→L3
-L2→L1
L3→L2
Rotation 90°
counterclockwise
-L1→L3
L2→L1
L3→L2
Rotation by an angle of θ L1cos(θ)-L2sin(θ)→L3
L1sin(θ)+L2cos(θ)→ L2
L3→L1
Horizontal stretch AL1→L1
Vertical stretch BL2→L2

The advantages of using plot sprites are:

  • The image data is stored in variables (lists), so the same code can display any sprite.
  • Plot sprites are usually smaller than hard-coded sprites, at a comparable speed.
  • As named lists, images can be saved outside a program without fear of being overwritten.
  • The sprites are uniquely easy to move (arbitrary rotation, for instance, is only possible with plot sprites)

The drawbacks are:

  • Since there are only three plots, only three independent sprites can be displayed at a time.
  • Plot sprites don't work well with other graphics: DispGraph erases most things drawn on the graph screen.
  • DispGraph erases before drawing, producing noticeable flicker.

There are two main avenues for plot sprites. The first is for displaying an image that won't have to be moved around (such as a title screen): this avoids the two problems that DispGraph causes. The other is for displaying a few images in complex motion, where the transformations can really come in handy.

Text Sprites

Text sprites are the most bizarre method (known so far) of displaying graphics. They are efficient in a very limited application: displaying small (usually 5x5) images without the drawbacks of hard-coded sprites. The idea is to display several characters very close to each other using the Text( command, so that the first pixel column of each character is combined into an image. For example:

:"([X[("→Str1
:For(X,1,5)
:Text(0,X,sub(Str1,X,1))
:End
:Text(0,6,"  ")

To understand what is going on, add a Pause command in the For( loop, and watch the image being drawn piece by piece.

When dealing with text sprites, the image data is stored in strings (in the example above, storing any other 5-character string to Str1 will produce a different 5x5 sprite). In fact, using properly chosen characters (see this chart), nearly any sprite with 5 rows (since small text characters are 5 pixels tall) can be displayed, with only a few rarely-encountered exceptions.

The advantages of using text sprites are:

  • At 5 pixels per byte (usually), they are the most efficient method of storing small images.
  • The sprites are not made up of points and lines, so they can be fairly detailed.

The drawbacks are:

  • Text sprites are usually slower than hard-coded sprites to display.
  • They are limited to a 5xN size, which makes them less flexible than other methods.
  • Displaying a text sprite erases a small space to the right of the sprite (this can be avoided with caching — see below).
  • Code to produce text sprites is harder to learn and understand.

Tilemaps are a good application for text sprites: the code for hard-coded sprites would be too large and unwieldy, and plot sprites are too limited in number. This is demonstrated in Donut Quest, a puzzle game whose graphics play to the strengths of text sprites while avoiding situations that would highlight their drawbacks.

Recently, someone came up with the idea of vertical sprites. It uses the same idea but it displays sprites from bottom to top. You can find more information in the Text Sprites page.

Layered text sprites

Similarly to text sprites, layered text sprites use the Text( command in order to display custom sprites very efficiently and are usually used in order to display an entire level at once rather than to draw a single isolated sprite due to their limitations, however they are faster than most methods for displaying large images and use very little memory (2 bytes for a single sprite). The idea is to draw a first layer of large font characters, saving them using StorePic, drawing a second layer on top of them and finally using the RecallPic command to join the 2 layers together, creating an horizontal line of sprites. For example:

:”NNNHHH”→Str1
:”OOOOOI”→Str2
:Text(-1,1,1,Str1)
:StorePic1
:Text(-1,1,1,Str2)
:RecallPic1

A variation of this method can be found in the game Serenity, where the second layer is shifted 1 pixel to the right, allowing the creation of 6x7 sprites and the removal of the gaps created between sprites when using the regular method.

Advantages

  • Each sprite only uses 2 bytes of memory
  • Due to the fast rendering speed of layered text sprites, they allow the entire screen to be filled very quickly, making them useful for drawing an entire level at once
  • The sprites allow for a lot of detail compared to other methods

Drawbacks

  • They are limited to a 5x7 or a 6x7 size, making them less flexible than other methods
  • Only a few different characters can be used, limiting the amount of shapes possible
  • Code to produce layered text sprites is harder to learn and understand
  • They are inefficient for displaying individual sprites

Due to the drawbacks of this method, layered text sprites are mostly used by platformers whose graphics resemble the home screen, such as Zoith, Metroid Pi and Serenity, for their ability to fill the graph screen very quickly when moving to a new screen.

Assembly Libraries

The fifth way to render graphics is to use an assembly library such as xLIB which includes sprite routines. These routines typically do what we all wish RecallPic could do: nearly instantly recall a small piece of a picture variable to an arbitrary part of the screen, often with extra features thrown in.

Choosing a library to use for your program involves trade-offs: an obscure program might have all the features you want, but a popular library will be used by other games as well. Users probably wouldn't mind installing one library to play a bunch of cool games, but if every game uses its own assembly library, managing them becomes tricky (particularly because they may interfere with each other).

The advantages of using assembly libraries for graphics are:

  • They are fast: usually faster than RecallPic, and definitely faster than any other method.
  • They are versatile: once you make the decision to use a library, it can be applied to any situation.

The drawbacks are:

  • An assembly library takes up lots of memory (not as much of a factor on newer calculators).
  • Typically, you will have to use a picture variable, with all the drawbacks that entails.

It's best to use assembly libraries only for graphics-intensive programs. If you do decide to use an assembly library, make as much use of it as possible: there's usually no point in going halfway and mixing an assembly library with any of these other tricks.

Advanced Techniques

Caching: with almost all of these methods, it takes some time to display an entire screen's worth of graphics. If there's a chance that this screen will have to be displayed more than once, it makes sense to avoid doing the extra work of drawing it all over again. To prevent this, take any unused picture variable, and use StorePic to save the current state of the screen. Then if it ever needs to be redrawn, RecallPic the screen instead of rendering it the normal way. This technique makes sense for a title screen (if it wasn't a picture variable already) or for the initial state of a level of a game (in case the player restarts).

A similar technique can be used when drawing one image will erase another part of the screen, and both are necessary. In this case, StorePic the screen, draw the image, and then RecallPic. Because RecallPic uses "OR" logic (a fancy way of saying it doesn't ever erase dark pixels), this will keep the background while still drawing the new image. This is critical when combining plot sprites with any other method, and often comes in handy with text sprites as well.

Greyscale: if a pixel flashes on and off very quickly, it will appear grey to the eye (because erased pixels need time to fade to white). Switching back and forth between two or more pictures gives the effect of using three colors (black, white, and grey) on a calculator that can normally only handle two. Because this needs to be done quickly, usually only programs using assembly libraries attempt this. An example using xLIB:

:Repeat getKey
:For(N,1,2)
:real(3,N,0,1)
:End
:End

In this case, pixels that are on in both Pic1 and Pic2 will be displayed as black; pixels that are off in both of them will be displayed as white; pixels that are on in one and off in the other will be displayed as grey.

With precise timing, this technique can be improved to produce multiple shades of grey. Suppose that in this example, Pic2 were displayed twice as long as Pic1. In that case, black and white pixels would be the same; however, a pixel that was on in Pic1 and off in Pic2 would be on 1/3 of the time, while a pixel that was on in Pic2 and off in Pic1 would be on 2/3 of the time. This would give four colors:

State in Pic1 State in Pic2 Result
off off white
ON off light grey
off ON dark grey
ON ON black

Even more shades are possible, but the more complicated the code, the worse the flicker. If you try for too much, eventually the "greyscale" will turn into two pictures quite obviously alternating onscreen. Given the limitations of TI-Basic, it might be best to stick to 3-color greyscale.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/graphics


Program Protection

Disclaimer: Program protection not only is rather limited in its effectiveness, but also acts as a hindrance towards maintaining the open and collaborative nature of the TI-Basic community: allowing others to study and learn from your code, and to use the techniques and concepts in their programs, increases the quality of TI-Basic programs being released.

You've just finished working on your latest, greatest program. You put in a lot of time and effort creating the program, and now you want to enjoy the fruits of your labor — showing it off to your friends at school. When your friends try the game, you get positive feedback and they tell you how much fun it is, and even ask if you could put the game on their calculators.

Now, you don't mind putting the game on your friends' calculators, but you want to make sure that no one can mess with it. Once the game is out amongst the school crowd, you know that other people will want the game so you need to come up with a way to protect your program. Fortunately, there are several ways to protect a program.

Before getting to program protection, the first thing you need to do is edit lock your program. You can edit lock a program using either one of the several downloadable assembly programs or the Graph Link software made by TI. It goes without saying that you should never give someone an editable version of your program.

Once your program is edit locked, now you can add a security function. Although there are several ways to protect a program, they each have varying degrees of complexity and success. The general rule is that the more complicated the protection is, the more difficult it will be for someone to circumvent it.

Put the Code Together

Arguably the simplest, yet most crude program protection method is just putting all of the code in the program on one line. You might recognize this as utilizing compact style, except this time it serves as a program safeguard instead of a stylistic choice.

In order to put code together, you need to separate each command with a colon (:). The colon closes everything except a literal string, in which case the colon will actually be included as part of the string. In order to prevent this from happening, you need to close the string with a quote before adding the colon.

:If A=2:Then
:Disp "Hello
:not(B→B
:End
can be
:If A=2:Then:Disp "Hello":not(B→B:End  // Note the closed string

There is one command that doesn't need a colon following after it — DelVar — but leaving it off can cause some problems. DelVar's are typically chained together with one variable after another (i.e., DelVar ADelVar B), but the DelVar command also allows you to take the command from the next line (it doesn't matter what command it is) and put it immediately after the DelVar (i.e., DelVar ADisp "TI-Basic").

This works for the majority of commands, but there are two cases in which the command will actually be ignored: the End from an If conditional and a Lbl command. Both of these cases can cause your code to not work correctly anymore, and so you should either add the appropriate colons between the DelVar's or re-organize your code to eliminate the situation entirely.

:If not(X:Then:-Y→Y:DelVar ZEnd
can be
:If not(X:Then:DelVar Z-Y→Y:End  // Note DelVar's position

When you put the code together it will wrap around to the next line (and keep wrapping around for however many lines are needed), which is useful because the average calculator user will not be able to read and understand the code then. More importantly, if they press a key to try to mess with the code it can have dire consequences. Specifically, if the user presses CLEAR, the whole line of code (i.e., the entire program) will be deleted.

Entering a Password

If putting all of the code together on one line seems rather complicated (and maybe not worth all that effort), a simpler program protection method is having the user type in a password at the beginning of a program. You then check the password against the stored password and allow the person to play the game if the passwords match or exit back to the home screen. You can have the password be whatever you want.

:"5552646472→Str1    // Store the password to a string
:For(X,1,.5length(Str1    // Loop every two characters for a key
:Repeat Ans
:getKey
:End
:If Ans≠expr(sub(Str1,2X-1,2    // Check if the user typed the wrong key
:Stop    // Stop the program and return to the home screen
:End

When editing the password string, you must keep the length divisible by two because of the For( loop and the If conditional check. Besides that, this code does not allow keys 102-105 to be included in the password. That shouldn't be too big of a problem, though.

Entering Seeds

You can use pseudo random number sequences as a sort of password protection. After seeding the rand command, the results generated will be unique to the seed that was chosen. If the seed takes on the behavior of a password, then a comparison of the rand function to one of its precomputed results will act as an authentication for that password.

For instance, 5→rand followed by a single use of rand will return .727803… on all calculators, so a test can be devised as follows:

:Input X    // Request a number
:X→rand    // Seed the random number generator
:If rand≠.7278038625    // Check if the first random number is not equal to this value
:Stop    // Stop the program
or
:If rand≠.7278038625
:Stop

Only when the user inputs the correct seed (or in the latter case, stores the correct seed to rand before running the program) will he be able to venture past this part of the code. The upside to this technique is that even if he does see the code, he won't be able to figure out what the password is just by looking at that number.

Going further with this, you can test for a result that is obtained only after a specific number of numtrials (i.e., uses of the rand command). After storing 7 as a seed, the third result will be .577519…, so having a test similar to the one shown above will mean that the code that follows it will only work on its third execution after the seed is stored manually — adding another layer of obscurity.

Hash Functions

While using the seq( command, the calculator can still interpret keypresses and store them to getKey. One possible way you can use this feature is to make a password function that asks the user to enter in the correct password before time expires:

:DelVar L1seq(getKey,X,1,200→L2
:For(A,1,dim(Ans
:L2(A
:If Ans:Ans→L1(1+dim(L1
:End
:If 5=dim(L1
:If max(L1≠{55,52,64,64,72
:Stop
:"Success!

The main problem with using this routine is that you have to create a huge list to have enough time to input a reasonable password. This can be fixed by replacing seq(getKey,X,1,200 with something that goes a little slower:

:seq(getKey+0rand,X,1,100)
:seq(getKey+0dim(rand(2)),X,1,100)
...

This does lose a bit of sensitivity, but this isn't a huge problem because the routine has a lot of sensitivity to begin with. Even adding +0dim(rand(2)) left the code still sensitive enough that it recorded every keypress of me simply brushing a finger across the keyboard of my TI-83+.

Put this together with the idea that we don't want to store the password itself (because that would be fairly easy to figure out), but rather a hash of the password — a numerical equivalent value for the password. This is easier than extracting the nonzero elements of a list. For example, sum(√(Ans is a decent option that doesn't care about the order of the keypresses. If you want an option that does, take cumSum(Ans)not(not(Ans first — this multiplies the last keypress by 1, the next-to-last by 2, the one before that by 3, and so on.

Here is an example:

:ClrHome
:Disp "Input Password
:seq(getKey+0dim(rand(2)),I,1,50
:If 106.322402=sum(√(cumSum(Ans)not(not(Ans
:"Success!

This example will display the message Success! if you enter the password AWESOME. Obviously, one of the main programs with using a hash function is coming up with the different hashes for the passwords, so here is a program that will assist you in making the hashes:

:{0→L1:0
:Repeat Ans=105
:If Ans
:Ans→L1(1+dim(L1
:getKey
:End
:sum(√(cumSum(L1
:DelVar L1Ans

Input your password and then press ENTER to get the appropriate number to test against.

Example password: HAL
Hashed result: 29.8632681

By replacing 106.322402 in the hash password program with 29.8632681, the password will be reconfigured to HAL.

Self-Modifying Code (SMC)

Another way you can protect your program is by using self-modifying code. SMC makes your code more difficult to understand, and by placing code inside a graphing variable, you are essentially hiding it. This prevents somebody who's not very knowledgeable from figuring out what it is.

A good example of this is where you have an If conditional, and you replace part of the condition with a graphing variable:

:If Xnot(Yint(rand
can be
:"not(Yint(rand→u
:If Xu

If this conditional is inside a loop, then you can modify the u variable later so that its code is something different when the If conditional is checked next time. For the average calculator user, this will make your code seem obfuscated, and they will be hesitant to mess with it.

Causing an Error

Depending on the protection used, you usually want to implement an error when it has been breached. The simplest error would be a message to the user. <error status> can be anything you want: see the methods below for when to cause an error.

:If <error status>
:Pause "ERROR! UNAUTHORIZED USE DETECTED!
:Stop

Unfortunately, this method allows the user to know when the error occurred and remove the error code by pressing ON when the error is displayed. A more secure method uses an error caused by the calculator that cannot be traced to specific code. The drawback of this method is that a custom error message explaining the problem cannot be displayed.

:If <error status>
:Goto XX

This code will cause a program to display ERR:LABEL because there is no label XX. It is one of the few errors that does not have the option to go to the code causing the problem, which makes it more secure. An experienced user will most likely be able to find the problem Goto, however.

The most complicated method of causing an error is to embed pieces of code that cause problems when <error status> is true. In the examples below, problems are caused when X≠20 (replace this with whatever condition you want). Unless the user is an expert, it will be difficult for the user to fix the errors.

:If 21=getKey(X=20    // Clear getKey
:L1(X=20→LSAVE    // Prevent saving
:A+X→A    // Use as a replacement to A+20→A
:max({17,21,35,42,55}=seq(5Aint(B(X=20)/fPart(C
    // Screw up a complicated command
    // Extremely difficult for someone else to figure out

Another option is to quit the program immediately. This is most effective in a large program, where users will have to pore through hundreds if not thousands of lines of code to find the problem code. In addition, make the program jump to the default quit routine instead of a new one to confuse users even more.

:If L1(31)=5    // Quit condition test
:Goto XX    // Default quit label
...    // Whatever code is in between the Goto and matching Lbl
:Lbl XX
...    // Stuff to do before quitting
:Stop

Storing the Protection Status

The other program protection methods all require one variable in which to store the protection status (the number of times the program has run for a "trial period", whether it is protected or not, etc.). You can use any variable for this, but each has its own advantages and disadvantages: a custom list is best (but somewhat difficult to implement) and a finance variable is second best.

  • Regular variables — Have the advantage of being readily accessible, but are not very suitable because they are frequently overwritten by other programs.
  • Finance variables — Built-in to the calculator and are somewhat hidden, so they are unlikely to be erased. You can access these variables by going into the Finance menu. The only uses of the finance variables are the Finance Application and other programs. If another program is using the finance variable you want to use, either use a different one or change the other program. However, all the finance variables are reset to zero when the RAM is cleared.
  • Custom Lists — Can be archived, and it is unlikely that some other program would use the same list name. However, the list is visible in the Memory Management menu, and a perceptive user may realize that it is being used for program protection and change it. To counter this, you can hide the value among other values in another list used by your program (for example, save lists).

Trial Periods

If you wanted your program to only run a certain number of times (a trial period), you will have to have a counter that counts the number of times the program has run and produce an error when the limit is reached. (See above for a discussion on which counter to use.) For this example, we will use the finance variable n for simplicity. Add something like this to your program:

:n+1→n    // Increment the counter
:If n>5    // If this is past the fifth time, free trial is over
:Goto XX    // Replace this with any of error methods explained above

That's it. The above code will cause an error message to be displayed after the user has reached the end of the trial period (used the program five times). You can change this however you want to fit your needs. Since the increment comes after the error, it will continue erring each time it is run.

Authorization Required

You can also set up your program so that only authorized/licensed users can run it. This method can be combined with the above method: Users can use the programs until their free trial is up and they have to become "authorized." To "authorize" an individual calculator, set n to a predetermined value.

There are two ways of doing this: either type in the value manually (and use Clear Entries afterwards to prevent the user from discovering it), or transfer n as part of a group containing your program.

:If n≠20    // If n=20, the calculator is "authorized"
:Goto XX    // If not, cause problems
    // You can replace this with any of the errors mentioned above

You can also use this method to lock some of your program's features in the "unauthorized" versions. For instance, in this example every user can use feature one (which is part of label 1) while only authorized users can use feature two (which is part of label 2):

:Menu("MAIN MENU", "FEATURE 1", 1, "FEATURE 2", 2
:Lbl 1 
<feature one, available to everyone>
:Lbl 2
:If n≠20:Then
:Disp "ONLY AUTHORIZED","USERS CAN USE","THIS FEATURE
:Else
<feature two, restricted>
:End

Keeping subprograms un-executable

Say you have a large program with many subprograms, the only correct way to run the program is to run the main one. So to keep subprograms from being run outside of the main one you create a pass-on key and have the subprograms check Ans to see if it matches.

PROGRAM:MAIN
:randInt(1,100→Z    //make a pass-on key, keeping it new each time so the user cant guess it
(...rest of code)
:Z                //Store the key as Ans
:prgrmSUB1            //Call the subprogram
PROGRAM:SUB1
:If Ans≠Z            //Check the key and end the program if it doesn't match
:Stop
(...rest of code)

Simple enough

Thoughts to Consider

While discussing program protection, it is important to mention that somebody who's a knowledgeable calculator user will be able to circumvent any program protection using either one of the downloadable assembly programs that can unlock TI-Basic programs or the Graph Link software. Because of this, program protection really is only possible when you are dealing with ignorant calculator users.

Besides knowing about knowledgeable calculator users, you should also think about how others would be able to learn from your code. The general consensus among the calculator programming community is that programs should be unrestricted so others are able to study your work, as long as they do not release it as their own.

Putting all the code on one line would be frowned upon in this case because other programmers don't want to have to deal with separating out the code one line at a time to be able to understand and read it; that's just a major headache. Just remember that experimentation is key to learning TI-Basic, so you don't want to deprive that opportunity from someone else.

References

  • David Martin had the ideas for "free trial" and "authorization" program protection in his TI-Basic guide, which unfortunately is not available on the Internet anymore. The examples given here are based on these ideas, but modified to fit this guide better.
  • Weregoose came up with the plain password code example, while DarkerLine and Weregoose came up with the hash function password code examples; the examples were originally posted on the United-TI TI-Basic forum topic.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/protection


Look-Up Tables

A lookup table consists of a list (or matrix, depending on the situation) that is used to store calculations, for which the time to look them up in the list is smaller than having to calculate them (hence the name). Lookup tables are commonly created at or near the beginning of a program for later use in the program.

The primary advantage of lookup tables is their speed. Simply getting a number from a list is much faster than calculating the number with an algorithm or using a trigonometric function. The primary disadvantage of lookup tables is their memory usage. Not only do you need to use an extra variable to keep track of all the numbers, but it is very possible that you can end up storing numbers that you won't even use.

Examples

For an example, let's look at using the trigonometric functions. Say we want to draw a circle using lines. We want to draw a line every 10 degrees, and because the circle has 360 degrees, that means we would do 36 calculations. Without using lookup tables, the approach would be to simply use the cos( and sin( functions:

:ClrDraw
:0→Xmin:1→ΔX
:0→Ymin:1→ΔY
:90→A:30→B
:For(X,0,360,10
:70+20cos(X→C
:30+20sin(X→D
:Line(A,B,C,D
:C→A:D→B
:End

Although this code draws pretty fast already, it could be made faster using lookup tables. Every time through the loop we are calculating the cos( and sin( functions, which is quite time-consuming. Speed is especially important in this particular example because we want to have the circle draw as fast as possible (it should be faster than the Circle( command). Here's what the example would look like using lookup tables:

:ClrDraw
:0→Xmin:1→ΔX
:0→Ymin:1→ΔY
:90→A:30→B
:seq(20cos(X),X,0,360,10→L1
:seq(20sin(X),X,0,360,10→L2
:For(X,1,36
:70+L1(X→C
:30+L2(X→D
:Line(A,B,C,D
:C→A:D→B
:End

Another example that should help you more fully understand lookup tables is getting user input. More specifically, combining the getKey command with a lookup table. Say you want to display a text character based on which key was pressed. A common way to do this is to check to see what the individual keycodes are and then display the respective character:

:getKey→K
:If K=41
:Output(4,X,"A
:If K=42
:Output(4,X,"B

What you could do instead is place all the acceptable characters (in this case the alphabet) in a string, and then put all the keycodes in a list, organized to follow the alphabet keycodes. When you want to display a character, you simply search the list for the keycode that the user pressed:

:getKey→K
:{41,42,43,51,52,53,54,55,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85,91,92,93
:If K>42 and K<94 and K≠45
:Output(4,X,sub("ABCDEFGHIJKLMNOPQRSTUVWXYZ",max(K=Ans and seq(B,B,1,dim(Ans))),1

(See Custom Text Input page for a smaller and faster way to get the keycodes.)

Conclusion

These are rather simple examples, but they should be enough for you to understand how lookup tables work and what you can use them for. Just remember that the battle of speed vs. size is left up to you to decide which route you take. The two main factors to consider are the playability of the program (if the game is slow, the calculations should go) and the number of times the lookup table will be used (if the use is one, consider it none).

References

  • The example trigonometric code was borrowed from David Martin's tutorial, which is not available on the Internet anymore.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/lookuptables


Self-Modifying Code (SMC)
Equation Variables
Function Y0-Y9
Parametric X/Y1T-X/Y6T
Polar r1-r6
Sequence u, v, w

Self-modifying code (SMC) is code that changes itself while it is executing. While TI-Basic does not provide support for SMC like it is found in other programming languages, TI-Basic does allow you to implement a primitive form of SMC using the equation variables that are used when graphing an equation on the graph screen.

The function, parametric, and polar graphing variables are accessible in the VARS menu (options 1, 2, and 3 respectively), while the sequence graphing variables are accessible on the keypad by pressing 2nd 7, 8, and 9 respectively.

Each of these variables is the same size, so there is no real difference between which variable you use. However, since sequence graphing is the least used graphing mode, the sequence variables are probably the best variables to use when using SMC.

How does it Work?

While the equation variables are primarily used for graphing, they are actually stored internally as strings by the calculator. The string operations and commands do not work on them, however, but you can store a string to them and evaluate them in an expression.

Just like how you can evaluate an expression stored in a string using the expr( command, the equation variables can be used the same way implicitly. The expression can contain whatever combination of numbers, variables, and functions that you want, just as long as they evaluate to a number or list of numbers.

For a simple example, let's initialize X with a value of 2 and store the expression "50X" to u:

:2→X
:"50X→u

When you access u, it will have a value of 100. But what would happen to the value of u if you changed the value of X to 5? Well, because the value of u depends on the value of X, u would change accordingly, and it would now have a value of 250. This is the basic premise of SMC: You can modify a variable elsewhere, and it will automatically update the respective equation variable. Hence, a program can change how it runs.

As it turns out, finding an occasion to use this technique is usually rare, so here is a made-up example. This program will count up and down with the arrow keys until you press ENTER. If you press 2ND, however, it will switch the order of the keys:

:5→A
:"(Ans=25)-(Ans=34→u        // initial expression for u
:Repeat Ans=105
:A+u→A
:Disp Ans
:Repeat Ans:getKey:End      // wait for a keypress
:If Ans=21
:"(Ans=34)-(Ans=25→u        // switch the arrow keys
:End

Advanced Uses

While just using SMC for simple expressions doesn't really add any additional value to your programs, you can use it for more complicated purposes. One common situation is optimization.

If you have a lengthy command or formula that you use multiple times throughout your program, you can simply store the statement to an equation variable, and then use the equation variable whenever you want to call the statement. This eliminates duplicate code, which makes your program smaller.

For example, if you want to generate a random integer from 1 to 9, here is what you would use:

:"randInt(1,9→u

Then each time you wanted to create a random integer, just use u.

Limitations of SMC

There are a few limitations you need to be aware of when using SMC:

  • It complicates your code, making it difficult to understand and maintain. This is why you should primarily stick to implementing SMC when you are done with your program.
  • The equation variables will affect the graph settings, and likewise the graph screen will be affected if the respective graph mode is enabled.
  • You can't store the equation variable to itself, or other variables, if they don't have a matching type (i.e., trying to store a string to a real will result in an ERR:DATA TYPE error).
  • Don't abuse SMC; the extra step of reading and executing through variables may slow down your code slightly and even cost a number of bytes if used improperly, so wield it wisely (i.e., only for the benefits it provides over other methods).

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/selfmodify


Grouping A Program

Your friend just asked you to transfer a program on your calculator over to his calculator so that he can play it in class whenever he wants to. You say sure, and he gets his link cable out and you start the transfer process. What you thought was going to be a simple transfer turns out to involve some serious headaches.

The program he wants not only has several subprograms that go with it, but multiple list and matrix variables as well as a few pictures. Unfortunately, you aren't aware of this until later after he tries to run the main program without the necessary subprograms, variables, and pictures.

When he asks you why the program won't work like it did on your calculator, you don't have an answer. You decide to start transferring over other programs and variables and whatever else to try to make the program work, but the program still doesn't cooperate. Finally you just give up and tell him that there must be something wrong with his calculator.

While this seems like a rather difficult problem to fix, there is in fact a simple solution: group files. Groups store files together in a package, where the file can be almost anything, whether it is a program, variable, picture, etc. Because groups reside in the archive, you never have to worry about a RAM clear deleting your group.

Advantages

Several files that go together can be put in one group, making it easy to transfer the files together — whether between two calculators, or a calculator and a computer.

On a TI-83+ or higher, group variables are stored in the archive, which means that a rogue RAM clear won't delete your files.

Groups are also great for backing up a version of a program being worked on before making major changes to it - even if the program is very large, or split between several files.

Finally, putting several parts of a released program in a group avoids the issue of users that forget to transfer a necessary file (although you should explain how groups work in a readme file).

Limitations

A group must contain more than one variable. It's possible to get around this by providing a dummy variable in the group (use a variable such as X that probably doesn't hold anything important).

TI-Basic programs cannot modify groups. You will have to recreate the group if you want to change its contents. Usually, this isn't too much trouble.

It's also been reported that in large enough groups, the calculator may change a bit in the data when ungrouping — in practice, this might result in an error when running the newly-ungrouped program. To be on the safe side, you should check that a group "works" before deleting the original files. It's also possible that splitting the large group in two (if this is feasible) will fix the issue.

References

  • The idea for this grouping article came from Jon Pezzino and Kerm Martian's "The Elite Guide to TI-BASIC". It is a good read with lots of useful knowledge and tips/tricks. You can find the link to it on the Resources page.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/grouping


Subprograms
toolbar-separator.png This article is part of the coding stage of the development cycle.

Imagine you're creating an RPG, and the current problem you're facing is how to display all of the data for each character on the screen. Without putting too much thought into it, the easiest approach to you seems to be to simply write out the data each time. Unfortunately, when you start implementing this approach, it soon becomes apparent that it will not work in your program.

While you've only programmed in a few of the characters and their respective data, you can already see that there is simply too much data to enter in; and then when you think about the possibility of having to go through and change all of the data again if you update the program, you're now left feeling overwhelmed and wondering if there's another way. Thankfully, there is, and its name is subprograms.

A subprogram is a program called by another program to perform a particular task or function for the program. When a task needs to be performed multiple times (such as displaying character data), you can make it into a separate subprogram. The complete program is thus made up of multiple smaller, independent subprograms that work together with the main program.

There are two different general types of subprograms available:

  • External — They exist as stand-alone programs that are listed in the program menu, and can be executed just like a regular program.
  • Internal — They are contained inside the program itself, so that they can be called by the program whenever needed.

There are certain advantages and disadvantages to using each type of subprogram, and consequently, situations where using one type of subprogram makes more sense than using the other. This doesn't mean you can't use whichever you like, though.

External Subprograms

External subprograms are the simplest type of subprogram, and involve executing one program from inside another program using the prgm command. You just insert the prgm command into the program where you want the subprogram to run, and then type the subprogram's name. You can also go to the program menu, and press ENTER on whichever program you want to use to paste the program's name into the program.

:prgmPROGNAME

When creating a subprogram, you take whatever code you want from the parent program and put it in its own program (see your first program for more information), and then put a Return command whenever you want to return to the parent program. (A Return command is optional at the end of a program, and you typically leave it off as part of program optimization.)

You should try to name your subprograms Zparentn or θparentn, where parent is the name of the parent program and n is the number (if you have more than one). Because subprograms are relatively unimportant by themselves, you want them to appear at the bottom of the program menu so they don't clutter it up and interfere with the user's ability to find whatever program they're looking for.

Here's a simple example where we are storing maps for our maze game in a subprogram, and then retrieving the desired map from the subprogram as a string, so we can print it out on the home screen. (This example is somewhat contrived, but it should be enough to illustrate external subprograms).

PROGRAM:MAZE
:ClrHome
:prgmZMAZE
:Output(1,1,Ans
:Pause

PROGRAM:ZMAZE
:int(3rand→A
:"X    XX    XXXXXX    XX    XXXXXX    XX    XXXXX
:If A=1:"X X X X X X X X X X X X X X X X X X X X X X X X 
:If not(A:"X              XX              XX              X
subprogram_zmaze.gif

When the subprogram's name is encountered (in this case, prgmZMAZE), execution of the program will be put on hold, and program execution will transfer to the subprogram. Once the subprogram is finished running, or the Return command is executed, program execution will go back to the program, continuing right after the subprogram name. (If the Stop command is used instead of Return, however, the complete program hierarchy will stop.) See the image to the right for a graphical view of program flow using subprograms.

Although subprograms can call themselves (i.e., recursion) or other subprograms, each subprogram should return to the parent program and let it handle all the program calling. A structured program hierarchy is easier to understand and update (in fact, it's actually a code convention), and helps cut down the potential for memory leaks.

Each program call is sixteen bytes, and gets put on a stack in RAM by the calculator. This is fine as long as its size isn't larger than the free RAM available, but each additional program call takes more memory until the program Returns. Having many nested program calls can run out of memory and crash the calculator (giving you a ERR:MEMORY error).

External subprograms often are made to increase the speed of a program and decrease the size of the program overall by executing often used code at one place, where it can be called quickly. (as opposed to Labels)

To make subprograms even faster, a Return may be used in the subprogram, but only is useful in subprograms with several methods, and only after a method has been completed. The problem with using a Return in such a method is that it isn't very easy to prevent memory leaks by using a Return before an End command should have been called.

Because the same thing happens with Goto's before End commands as Returns before End commands, we can use this to our advantage, to quickly return from a subprogram. By using a Goto to a label with one or possibly more End commands, you can quickly return from a program, or quickly reset a While, Repeat, or For( loop without having to execute the rest of the code in the subprogram or loop.

Goto ST
Lbl E1
End
Lbl E0
Return
Lbl ST
[code]
If [condition]
Goto E0
[code]
If [condition]
Then
[code]
Goto E1
End
For(A,1,10
[code]
If [condition]
Goto E1
[code]
End

This can significantly increase the speed of subprograms or loops, by using Labels without worry of ERR:MEMORY.

Passing Arguments

The main problem associated with trying to use external subprograms is that there is no built-in support for passing arguments to subprograms. This feature is important because it allows the subprogram to act differently based on what values are given to it for processing.

Fortunately, you can mimic this functionality by using variables. Because all variables are global (variables used by one program can be used by another), changing a variable in one program affects that variable everywhere else. While you can use almost any variable that you want, there are three main types of variables that you should choose from:

  • Pre-Defined Variables — Includes reals, strings, matrices, built-in lists, etc. These variables are frequently used by most programs, so you don't have to worry very much about whether the user cares if your mess with them.
  • User-Defined Lists — Uses the individual list elements to store different values. These variables have a certain sense of security that comes with using them because they are the only variable that you can actually create, so a program can have its own custom list to use.
  • Ans — It can take on whatever value and variable you want, so the program doesn't have a specific variable hard-coded in. Its value changes whenever you store something or simply place an expression or string on a line by itself.

When using a pre-defined variable or user-defined list, you simply have to set the variable to the value that you want and then call the subprogram. The subprogram should be able to use that variable without problems, but if you don't properly setup the variable, the subprogram won't work correctly.

:{2,3,5,7,9→PRIME
:prgmZPRIME

Using the Ans variable is essentially the same, except you need to add some additional code to the subprogram. Because the value of Ans changes whenever there is a new variable storage, you should have the first line inside the subprogram save Ans to another, more stable variable.

:{2,3,5,7,9
:prgmZPRIME

PROGRAM:ZPRIME
:Ans→PRIME

This change saves some memory in the main program (in our example, we were able to get rid of the →PRIME statement), but the subprogram size is larger, since we really just shifted the variable storage code to the subprogram. However, if the subprogram is called multiple times this extra memory is only used once instead of once per call.

This does create a problem, though, because now when you store Ans to another variable, it will crash the program if Ans isn't the same type of variable. There is only one case where you can avoid crashing when the subprogram receives the wrong variable type. If the subprogram is expecting a real variable (such as A or X) and it is passed a list, it can prevent a crash by using the fact that a parenthesis ("(") has multiple functions.

PROGRAM:ZSUB
:Ans(1→A

The reason that this works is because a user-defined list doesn't need the ∟ prefixed character at the beginning when referring to the list. While you may be only asking the user to input a simple real variable, a list would also be allowed. There is nothing you can really do to fix this problem with other types, so just be careful.

Advanced Uses

The main consideration when using external subprograms is how many subprograms your program should have. While you're still putting your program together, it's good to keep it in many small, separate subprograms; but when you're done, all those subprograms become a liability and make your program unwieldy to use. This is because you have to remember all those subprograms in order to use your program.

There are two different ways to resolve this problem. The first way is to put the subprograms back in your program. This should only be done if a subprogram was only called once or twice, and putting it back in won't slow down the program. All you have to do is paste the code from the subprogram in place of the subprogram call. When you're done, you can delete the now unnecessary subprograms.

(The more detailed explanation is to go through your main program, and whenever you see a prgm call for a subprogram, clear that line and press 2nd STO. The Recall option will come up. Press the PRGM key and select the appropriate subprogram from the EXEC menu. The calculator will paste that subprogram's code into the main program.)

This is the same subprogram example from before, but now we've gotten rid of the ZMAZE subprogram and simply placed the subprogram code in the MAZE program itself:

PROGRAM:MAZE
:ClrHome
:int(3rand→A
:"X    XX    XXXXXX    XX    XXXXXX    XX    XXXXX
:If A=1:"X X X X X X X X X X X X X X X X X X X X X X X X 
:If not(A:"X              XX              XX              X
:Output(1,1,Ans
:Pause

The second way to resolve the problem is by simply combining your subprograms together, so that there are fewer subprograms needed. Of course, how many subprograms you decide to use is up to you, but you should try to limit it to three or four subprograms at most, and just one subprogram ideally. This might take some effort on your part, but it will most certainly make your users happy.

When you start combining your subprograms together, you should place the subprograms one after the other, giving each subprogram a unique branching label (note that labels are local, so you can't use Goto in one program to jump to a label in another program). Instead of having to search through each individual subprogram, branching allows you to simply jump to the desired subprogram. You then just use the subprogram's variable argument to determine which subprogram to access.

:If A=e:Goto A  // jump to first subprogram
:If A=π:Goto B  // jump to second subprogram
:Stop  // the subprogram was accidentally called
:Lbl A
: // subprogram code
:Return
:Lbl B
: // subprogram code
: // No Return needed here

Looking at the example, the first thing you should notice is the variable values that are used to determine which subprogram to jump to. While you could use something simple like one or two, those values have a high probability of being accidentally entered in by the user or being set by another unrelated program. What works better is to use random decimals (like .193 or 1.857) or math symbols (like e or π).

If none of the variable values for the subprograms match, then none of the subprograms will be executed; instead, program execution will go to the Stop command on the next line, which will immediately stop the entire program. The reason for adding this program protection is to prevent the user from running the subprogram separate from our main program.

This is a real concern since external subprograms are listed in the program menu, and the user most likely at some point will try to run the subprogram just out of pure curiosity. Unless the user is a competent TI-Basic programmer who knows what they are doing, however, you normally don't want to let the user mess with your subprograms. If they change something, or delete some lines of code, then your program might stop working correctly.

The second thing you should notice about the example is the Return command at the end of each subprogram. If you have lots of subprograms, and you're accessing a subprogram near the bottom, it takes a considerable amount of time for program execution to go back to the main program. This happens because program execution doesn't return to the main program until after it reaches the end of the program, or it executes a Return command. So, just remember to include the Return commands as needed.

Using Assembly

Although using assembly programs can limit the compatibility of your program, they can be helpful in reducing the memory your program occupies, and allow for easier calling of subprograms. To use an assembly program for calling subprograms, have your subprograms named using some very simple pattern (e.g. "ZZ10", "ZZ11", "ZZ12", "ZZ13", etc). Then create a program such as the following called ZEXEC (or something similar):

:"ZZ"+Ans→StrX
://Assembly program to run program name in StrX

Then you can call this program through the line:

:"13
:prgmZEXEC

This will create a string with the contents "ZZ13" which will then run the program ZZ13. Depending on the assembly program you are using, you could have "ZZ13" archived (along with the rest of the subroutines) and when ZEXEC is called, it copies it to an unarchived program, runs the copy, and then deletes the copy, thus only one subroutine at a time is unarchived. This is useful for programs with lots of subroutines. One way of doing this is using xLIB, for which the ZEXEC code would look like this:

"ZZ"+Ans
real(10,0,0
prgmXTEMP000
real(10,1,0

In order to make this concept more efficient, a number to string routine would come in handy. If one were using such a routine one could have various actions in a program return number values. These numbers would be converted into strings and the program would run the corresponding subprogram. This would become useful with a custom menu, one could have the program return the location of the cursor, convert that into a string and run the subprogram that corresponds to that cursor location. Some assembly programs that can be used may be found on the assembly libraries page.

Advantages

There are several advantages of using external subprograms. First, and foremost, they reduce program size by eliminating redundant code. Instead of having to type the code multiple times for a task that occurs more than once in a program, you just type it once and put it in a subprogram. You then call the subprogram whenever you want to perform the task in your program.

Second, external subprograms increase program speed by making programs as compact as possible. You separate conditional tasks from the program (they either happen every time or they are skipped over), and put them in a subprogram; you then call the subprogram instead. This improves program speed because the calculator doesn't have to go through all of the conditional code anymore.

Third, external subprograms make editing, debugging, and optimizing easier. Instead of going through the entire program, looking for the code you want to change, you can focus on one subprogram at a time. This makes the code more manageable, allowing you to more thoroughly look at each subprogram and to better keep track of which subprograms you have looked at. It also prevents you from accidentally changing other parts of the program.

Lastly, subprograms are reusable, allowing multiple programs to share and use the same code. Breaking a program into smaller, individual subprograms, which each do a basic function or task, allows other programs to use those subprograms. Consequently, this reduces program size.

Internal Subprograms

Internal subprograms are the most complicated type of subprogram, and involve putting the subprograms in the main program itself. This is not the same thing as pasting the code from the subprogram in place of the subprogram call, like you do with external subprograms; rather, it is designing your main program so that it can take advantage of subprograms, but all the code is self-contained.

There are several different ways that you can make internal subprograms, but the three most common ways are:

  1. Append to the beginning of the program
  2. Structured loops or branching
  3. Branching out of broken loops

Append to Program Beginning

If you remember how we used external programs, then this should be very familiar. Instead of placing the subprograms in their own separate program, we are now just placing the subprograms at the beginning of our main program.

The standard way to make a subprogram is to use an If-Then conditional:

:If A=1.234:Then
: // subprogram code
:DelVar A
:Return
:End

Then to call the subprogram, you just set the variable to the desired value:

:1.234→A
:prgmPROGNAME

Of course, there are some important considerations that you need to be aware of. You can use whatever random value for the variable that you want, just as long as it isn't something that the user would typically use. This is to ensure that the subprogram isn't accidentally run when it shouldn't be, which is why you need to reset the variable's value inside the subprogram before exiting.

While you could use any variable that you want (including Ans), the best variables to use are the simple real variables (A-Z and θ). This is because they are small in size and they are constantly being used by other programs, so you don't have to really worry very much about your subprograms being accidentally run. (Ans is not a very good variable to use for the reasons listed above.)

You should always remember to include the Return command at the end of the subprogram. Once the subprogram is finished, the Return command will cause the subprogram to stop and return to the previous place in the program from where it was called. The other reason for the Return command is to prevent any memory errors that can occur if a program recursively calls itself too much.

Advanced Uses

You can have multiple subprograms at the beginning listed one after the other by simply using different values for the the variable:

:If A=1.234:Then
: // subprogram 1
:End
:If A=2.246:Then
: // subprogram 2
:End

While this works quite well when you only have three or four subprograms, with more subprograms it can actually slow down the main program. This happens because the calculator has to go through all the subprograms to get to the main program code.

You could fix this problem in a couple different ways, but the easiest way is to simply place all the subprograms in an If-Then conditional and then make that part of the subprograms. If this conditional is false, all of the subprograms will be skipped over.

A real number has an integer (accessed with the iPart( command) and fraction (accessed with the fPart( command) part, and you can use both of those for the subprograms: the integer will be the subprogram access check on the outside If-Then conditional and the fraction will be the respective subprogram we want to run.

:If 123456=iPart(A:Then  // get integer part of number
:10fPart(A  // get fraction part of number
:If Ans=1:Then
: // subprogram 1
:End
:If Ans=2:Then
: // subprogram 2
:End
: // rest of subprograms
:End

For calling the subprograms, you then just set the variable to the desired value like before:

:123456.1→A  // run subprogram 1
:prgmPROGNAME

Structured Loops or Branching

If you don't like placing subprograms at the beginning of a program, the next approach that you can try is placing subprograms in the actual program code. While it would appear easy to simply place the subprograms wherever you feel like in your program, you can't readily do this since it would almost certainly cause your program to stop working correctly. Instead, you need to modify your program and subprograms so they can be put together.

What this modification entails is reorganizing your program so that the code works in a modular fashion as individual subprograms. This may not seem like it would be worth the effort, depending on the amount of code in your program, but modularization makes the program easier to understand and update (see planning programs for more information).

While there are several different ways you can structure the code in a modular fashion, the simplest way is to give each subprogram its own individual loop with a respective variable value as the loop condition. You can then access and exit the desired loop by simply changing the value of the variable. Of course, you have to determine which loop and variable you are going to use.

There are three different loops you can choose from (While, Repeat, and For(), but the best loop to use in this circumstance is While. This is because the condition is tested at the top of the loop, so if it's false already before the loop, then the loop will actually be skipped over (which is what allows us to use the loops as subprograms).

Once you have decided upon a particular loop, now you need to choose which variable you want to use. Like with the first way to make internal subprograms, the best variable to use is one of the real variables (A-Z and θ). This is because we just need a single value, and real variables only take up 15 bytes of memory (other variables are just as small, but they take up more memory when you're accessing them).

Now that the loop and variable have been chosen, we need to setup the system of loops to act as the subprograms. What works best is to have a main program loop and then place the subprogram loops inside of it. Putting the variable and loops together, here is what the program skeleton looks like:

:Repeat not(A  // main program loop
:1→A
:While A=1
: // subprogram 1
:2→A  // enter loop for second subprogram
:End
:While A=2
: // subprogram 2
:DelVar A  // exit main program loop
:End
: // rest of subprograms
:End

You just set the value of the variable in the loop to use the desired subprogram. Then when you are done with the subprogram, you just change the value of the variable to something different to exit the loop. You do the same thing to exit the main program loop. You can use whatever system of values for the variable that you want, but just remember to keep it simple enough so that you can come back to it later and it still makes sense to you.

The one drawback of using this approach is that the calculator has to go through all the subprograms to exit the main program loop, which can really be slow depending on the size of the subprograms. At the same time, this approach is very easy to understand and follow because the loops are organized in a straight forward manner, so it's kind of an even trade off.

Related to using structured loops, the alternative you can use is branching. While using branching by itself to structure a program is generally frowned upon (see planning programs for more information), you can actually use it quite effectively for making internal subprograms that only need to be called a few times. Here is a simple example:

:0→A:Goto A
:Lbl B
: // main program code
:1→A:Goto A
:Lbl C
: // main program code
:Stop
:Lbl A
: // subprogram code
:If A:Goto C
:Goto B

The A variable is used for determining when to stop the program: a zero value will simply cause the subprogram to jump back to the main program, but a value of one will cause the subprogram to jump to the exit of the program (the C label). Because the calculator doesn't store the label positions, there is no way to get memory leaks using this approach, which is especially important when exiting the program. However, it does get hard to follow and maintain the code the more branching there is.

Branching out of Loops

The last way to make internal subprograms is arguably the most difficult to understand, but once you have it setup in your program, it provides an easy framework for adding additional subprograms. The best time to use these kind of subprograms is when you have a main program loop that you're running and you want to be able to jump out of it and then back into it whenever you want.

The basis of these subprograms is using branching (Goto and Lbl) with loops and conditionals (anything that uses an End command). Branching by itself allows the calculator to jump from one point in a program to another, skipping over whatever code you don't want executed. When you use branching to exit loops and conditionals, however, it has the unwanted effect of causing memory leaks.

Memory leaks happen because the calculator doesn't get to reach the End command for the associated loop or conditional, and the calculator just keeps on storing the End commands in its stack until there is eventually no free memory left. (Memory leaks can also occur with excessive program recursion.) Here is a simple example that has a memory leak:

:Lbl A
:While 1
:Goto A
:End

If you notice, when the Goto A command is executed, it jumps to the matching label A that is on the line before the loop. The While 1 loop is never allowed to finish because the End command never gets reached, and the branching occurs over and over again until the calculator finally slows down to a stop (because there is less and less free memory available) and returns a memory error.

This type of programming is common with beginners, and its use is generally frowned upon; instead you should try to use proper program structure (see planning programs for more information). However, if you know what you are doing, you can actually use these broken loops and conditionals for internal subprograms, and you won't have to worry about memory leaks or the dreaded memory error.

There are two different approaches that you can use. The first approach is to use another Goto and matching label to jump back into the loop. Because the calculator doesn't store the labels, you can freely use whatever branching in the loop that you want, and the calculator will act like it had never even left the loop:

:Repeat getKey
:Goto A
:Lbl B
:End
:Stop
:Lbl A
: // subprogram code
:Goto B

The key here is that the Goto A command jumps to the matching label A outside the loop, and then the Goto B jumps to the matching label B back inside the loop. The calculator still has the loop's associated End command on its stack, so the loop will just keep looping without problems until you eventually press a key to stop it and it executes the Stop command.

While this first approach works rather nicely in small programs, it is not very practical for use in large programs because all the branching starts to slow the program down. Unlike loops and conditionals, the calculator doesn't keep track of the label positions, so it must start from the beginning of the program to find the matching label to jump to. The further down the label is in the program code, the more time the calculator must spend looking for it.

The second approach solves this problem by using a duplicate End command for the loop or conditional. Since the calculator keeps track of the number of unfinished loops and conditionals by storing the associated End commands in its stack, we can make the calculator believe that our different End command is actually the End command that belongs to the loop. Here is a simple example to illustrate:

:Repeat getKey
:Goto A
:End
:Stop
:Lbl A
: // subprogram code
:End

Like with the first approach, when Goto A is executed the program will jump to the matching label A, and then the subprogram code will be executed. This time, however, the calculator will read the End command after the subprogram code, which it believes is the end of the loop, and then immediately jump back to the beginning of the loop. This process will be repeated over and over again until the user presses a key, at which time the Stop command will be executed and the program will stop.

The subprogram code for both approaches can be whatever you want, including other loops and conditionals. You just need to remember to close the loops and conditionals before returning to the original loop, otherwise the calculator will have the wrong End command on its stack. You also want to have a matching number of End commands for your loops and conditionals, or you will get a memory leak.

Advanced Uses

There are a couple different ways you can enhance the duplicate End subprogram approach so that you get the most use out of it. The first way is relatively simple, and just involves using a For( loop as the looping structure, instead of a While loop or Repeat loop (which is what we had in our previous examples).

A For( loop is basically a specialized form of a While loop, with the main differences being that it is executed a specific number of times and it has the variable setup and ending condition built-in. You just choose a variable, the range of values, and the increment (it is optional, with one as the default); and then the loop will start the variable at the initial value and increment it each time until it reaches the ending value.

Now when you start using the For( loop for internal subprograms, you need to make sure the For( loop executes at least twice. This is so that the End command of the For( loop gets used along with the End command of the subprogram, otherwise it will simply fall through after the first time through the loop. You can select different subprograms based on the variable's value. Here is our example from above, now using a For( loop instead:

:For(A,0,1
:If not(A:Goto A
:End
: // main program code
:Stop
:Lbl A
: // subprogram code
:End

When the For( loop is executed, the A variable is set to zero. The not(A condition is true, so the calculator executes the Goto A command and then jumps to the matching label A. The calculator then jumps back to the beginning of the For( loop and increments the A variable to one. This time, however, there is no subprogram jump taking place, and the calculator simply finishes the For( loop like normal.

The second way to enhance the duplicate End subprogram approach is by using a simple trick. Because a While loop loops only when the condition is true, when the calculator comes across a While loop with a false condition, it will simply skip over the entire loop (and everything inside the loop). The easiest way to make a false condition is to use zero, since zero will never be true (based on Boolean logic). Here is a simple example to demonstrate:

:While 0
:Lbl A
: // subprogram code
:End
: // main program code
:If getKey:Then
: // program code
:Goto A
:End

When the calculator encounters the While 0 loop, it won't execute it because 0 is false. After the calculator enters the subprogram conditional, it executes some program code and then hits the Goto A command and jumps to the matching label A inside the While 0 loop. The calculator takes the End command of the loop as the End command of the conditional, and thus no memory leak occurs.

The reason that this trick is so valuable is because it allows you to place your subprograms at the beginning of the program, and you don't ever have to worry about them being accidentally executed (they will always be skipped over). In addition, now that the labels are at the beginning of the program, there is no more speed problem to deal with, since the calculator doesn't have to search through the entire program to find the labels.

Advantages

The main advantage of using internal subprograms is that there is only one program needed to make your program run. When you give someone your program, you don't have to worry about forgetting to include any subprograms; or somebody deleting your subprograms afterwards, causing your program to stop working correctly. These things are mostly out of your hands, but users will think your program is at fault.

Related to the first advantage, the other advantage is that the user's program menu doesn't get cluttered up with insignificant subprograms. This problem is relative to how many subprograms a program has, but it can become tiresome to have to sort through the program menu in order to find the program that you want. If anything, this is just a nice courtesy to the users of your programs.

References

<< Commenting Code Overview Program Cleanup >>

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/subprograms


Multiplayer
toolbar-separator.png This article is currently in development. You can help TI-Basic Developer by expanding it. I will get around to finishing this, probably during the Summer Holidays. ~ James Kanjo

Multiplayer is where two or more people play a game together at the same time. Although you can create AI opponents for a player to play against, AI does not offer as much fun compared to playing against other human opponents — you can have the players work together, compete against each other, and even one player manage the other players.

Multiplayer games are generally divided into two categories: the players share a single calculator, and the players each play on their own calculator connected together with a link cable (either I/O or USB).

Single-Calculator Multiplayer

Multiplayer games on one calculator generally fall into two categories: real-time and turn-based. Real-time is where the game action is constantly changing, not stopping for the player input. Some classic examples of real-time games are Galaxian and Pong. Turn-based is where each player is allowed to make a move, and the game action only changes after each player has moved. Some classic examples of turn-based games are Battleship and Scorched Earth.

Making real-time games involves using the getKey command, except you can't wait for a key to be pressed. The general form is something along the lines of:

While <game not done>
getKey->K
If K=<player 1 key>:Then
// player 1 action
End
If K=<player 2 key>:Then
// player 2 action
End
<Update rest of game>
End

As you can see, the player action only occurs when a player has pressed a particular key; otherwise the game just continues on like regular, with the main game loop being repeated over and over again.

There are some problems with making real-time games, however.

The first, and foremost, problem is that TI-Basic is rather slow with user input. If you do anything remotely time-intensive, such as displaying lots of graphics or complex variable manipulation, then there will be some lag-time between when a player presses a key and when the calculator gets around to processing it. Although there's not really much you can do about this, you can make sure your game is as optimized as possible (especially breaking the more time-intensive parts into their own subprograms).

The second problem is that the calculator only keeps track of the last key pressed since the last time getKey was executed, so that means only one player can have their input read and processed each time through the game loop. In addition, if you enter a large block of code for the player, it will take a while before the other players have a chance to do anything.

Related to the second problem, the third problem with making real-time games is that unlike the other keys, the arrow and DEL keys can actually be held down, which will cause them to keep being repeated until they are unpressed. The effectively disables the other keys from being able to be pressed. There is no viable way to get around this problem, except asking the players to not press those keys.

The fourth problem is that the keypad is quite small, and having two or more people try to share the calculator can be rather difficult. The best way to work around this problem is choosing keys for each player that are a good distance away from each other. When choosing keys you should also keep in mind the calculator screen — if somebody has to press keys that make it difficult to see the screen, then you should choose different keys.

Because making real-time games is not very practical, a better alternative is turn-based games: you hand the calculator from player to player, allowing each each player to move one at a time. These games are much easier to program: you simply use a variable to keep track of whose turn it is, increment the variable after each player's turn, and when everybody has completed their turn, you reset the variable. The only real downfall of turn-based games is that they can be slow because you have to wait until the other players are done before you can move.

Multi-Calculator Multiplayer

So I guess you're wondering how to program a multi-calculator multiplayer experience into one of your games. One of the first things you will need to do is familiarize yourself with the GetCalc( command. Basically, it retrieves a specified variable from another calculator and stores it to that variable on yours.

Creating multiplayer programs over two calculators is a much less simple process as it is to make single-calculator multiplayer programs. However, doing so could be the main selling point of your program and would certainly be worth the effort. You will notice that in each of our examples we tend to transfer lists, which we recommend you do too. Whilst it is possible to transfer a variety of real variables, it is much faster to transfer a list of numbers than a number of real variables.

There are two general ways to programming multi-calculator programs; one screen processing and two screen processing. The one screen processing method is simply making a program use the statistics from another calculator, and the whole multiplayer experience is processed on that calculator. The two screen processing method is much more complex, where we can share the multiplayer processing across two calculators by using a "turn-by-turn" interface.

Core

When it comes to multi-calculator multiplayer games, it is absolutely necessary to give each calculator its own identity. As both calculators are running the exact same program, we need a way to be able to determine one calculator as "Calculator A" and the other calculator as "Calculator B". This makes it possible for both calculators to know what data to send and receive. For example, if both calculators were "Calculator A", then both calculators would be doing exactly the same thing, or keep trying to receive the same variable from each other in an endless loop

This is code determines which assigns each calculator with a unique identity:

:GetCalc(A
:e(A=π)+π(A≠π→A

How it works is that the calculator gets the variable A from the other calculator, and checks whether it equals π (pi). If A equals π, then e is stored to A; however, if A does not equal π, then π is stored to A. Here is a table to demonstrate the results:

Calculator A Calculator B
A = π A = e
A = 3.141592654 A = 2.718281828

The calculator can therefore identify itself like this:

:If A=π:Disp "I'M CALC A
:If A=e:Disp "I'M CALC B

If we use a not( routine to make Calculator A = 1 and Calculator B = 0 instead, then we are unable to determine whether a link has been initiated. Simply explained, because variable A is more likely to equal zero than any other number, Calculator A may accidentally assume Calculator B has initiated the multi-calculator sequence. Variable A is not likely to ever equal π (or e), which is why it's useful as a "connection initiated" checker for the calculator.

The beauty of the core code is that it doesn't matter which player executes the core code first, both calculators will be able to give themselves a unique identity, be able to distinguish which calculator they are and be able to see whether the other calculator is initiated yet.

One Screen

If you are looking to save space and valuable time, this is the multiplayer for you. This method has the sending calculator in a power-saving state the whole time while the receiving calculator does all of the hard work such as processing and animation.

First off, we put in the core multiplayer code to determine which calculator is which. Then, Calculator B will retrieve the opponent's statistics for battling. Because the program uses the same variables on every calculator, we need to find a way to store Calculator A's statistics onto Calculator B without overwriting Calculator B's statistics. Surprisingly, this is not as hard as it seems:

:GetCalc(A
:e(A=π)+π(A≠π→A
:If A=π:Then
:∟STATS→L₁
:Disp "SENDING DATA...","PRESS ENTER WHEN
:Pause "FINISHED
:End

Now that each calculator has created its unique identity, and Calculator A has stored its statistics to L₁, we can finally make Calculator B receive Calculator A's statistics and process all of the data:

:If A=e:Then
:GetCalc(L₁
<interactive code>
:End

After this, write the rest as though this was a single-calculator multiplayer game, where you're statistics are in ∟STATS and your opponent's statistics are in L₁. Here is a side-by-side comparison on how the program runs:

Calculator A Calculator B
1SCREEN-A.gif 1SCREEN-B.gif

Two Screens

Here we show you a turn by turn based method of a battle game.

Like with all multi-calculator multiplayer programs, we first provide the program with the core. This time, however, we will first reset variables A and F. Then we will add code for which stores each calculator's statistical data to its individually named list. Calculator B is then instructed to go elsewhere in the program (note that Goto is within an If-Then loop):

:DelVarADelVar FGetCalc(A
:e(A=π)+π(A≠π→A
:If A=π:Then
:∟STATS→L₁
:Else
:∟STATS→L₂
:Goto W
:End

Because this is turn by turn battle game, we need to repeat the battle code until the battle is finished. We will make variable F determine this. Also, we want Calculator A to be able to attack first, so we shall put the code for attacking as the first thing in the Repeat loop. This is where it starts to get a bit sticky. First we delete variable B, which is going to determine what command the user has chosen (whether it be a kind of attack, or to run away).

:Repeat F
:DelVar BMenu("CHOOSE ATTACK","ATTACK A",A,"ATTACK B",B,"RUN AWAY",R
:Lbl A:1→B:Goto S
:Lbl B:2→B:Goto S
:Lbl R:‾1→B
:Lbl S:1→θ

So when the user selects an option from the menu, a number is stored to B and 1 is stored to θ. Theta tells the receiving calculator that it the sending calculator is not ready yet. Then we create a second menu. This is to give the receiving calculator a chance to receive certain variables. That process is almost instant, and so the user then presses ENTER. θ is erased and 1 is stored to S, just before the "animation" program starts. S simply tells the animation program that it has just sent the attack.

:Menu("SENDING ATTACK","READY?",SA
:Lbl SA:1→S
:DelVar θprgmθANIMAT

The animation program is shared by both the attacker and the attacked. The program makes particular animation depending on whether variable S is equal to one. If S=1, then this program will only display the opponent getting hurt. If S=0, then this program will display YOU getting hurt, calculate how much HP you have left, and if you died, sets variable F to zero. By using the subprogram "prgmθANIMAT", it means we don't need to worry about memory leaks or program changes.

Now we have the receiving code. You will notice that Lbl W is the first line here. This is so that Calculator B can jump straight here on the first move. Because this label is within a repeat loop, and the Goto came from an If-Then section, there are no memory leaks. The first thing we do is make the program wait until the sending calculator has issued a move. If the game is over (F=1), then this process stops, and the program exits the "Repeat F" loop. If the game is not over, and the opponent issued a move, then the calculator receives the opponent's updated statistics.

:Lbl W:Disp "WAITING...
:DelVar BRepeat B or F
:GetCalc(B
:GetCalc(F
:End
:If not(F:Then
:If A=e:GetCalc(L₁
:If A=π:GetCalc(L₂

At the moment upon entering the loop, we know that the opponent's θ equals 1. In this loop, we clear our θ variable and then retrieve the opponent's θ. Because of the nature of GetCalc(, we can not receive variables whilst the other calculator is processing. Remember that as soon as the other calculator exits the "SENDING ATTACK…" menu, the animation subprogram starts.

Using this knowledge, if we delete θ and then retrieve θ whilst the opponent is in the "SENDING ATTACK…" menu, θ will equal 1 (and hence the loop is repeated). But when the opponent starts the animation process, we will be unable to retrieve θ, and so θ will equal what it all ready was, zero (hence we exit the loop).

:Repeat not(θ
:DelVar θGetCalc(θ
:End
:DelVar SprgmθANIMAT
:End
:End

This code is rather remarkable because it makes it possible to start the animation on both calculators, at the same time, automatically. You don't need to go messing about with "both users press ENTER at the same time" routines, only one user needs to press ENTER and both calculators begin — a foolproof technique.

If, after the animation process, the battle is not yet over, then the program continues into attack mode again (at the start of the "Repeat F" loop).

Now we need a routine which restores the statistics to the ∟STATS list and says who won after the battle is over! This is the easiest part of the routine. If the player's health points do not equal zero, then that player won — otherwise the other player won.

:L₁
:If A=e:L₂
:Ans→∟STATS
:If Ans(6:Then
:Pause "YOU WON!
:Else
:Pause "YOU LOST!
:End

There are a couple of things that you need to be aware of for this routine to be work:

  1. When the "SENDING ATTACK" menu pops up, you must wait for a second for the attack to actually send before pressing ENTER;
  2. Variable A must NEVER equal π during the program, (obviously with the except of the multi-calculator code itself). If it does, and a different calculator starts this routine before the other one, then the link process will fail.

To prevent the second problem from ever happening, you should reset variable A at the start of your program, and never use this variable throughout the program.

This whole routine is certainly complex, but it does work, and works pretty well too. Here is a side-by-side comparison of how the program runs. For reference, here is a table showing the values:

Calculator A Calculator B
Max HP ∟STATS(1)=2 ∟STATS(1)=5
Level ∟STATS(2)=2 ∟STATS(2)=5
Attack ∟STATS(3)=2 ∟STATS(3)=5
Defence ∟STATS(4)=2 ∟STATS(4)=5
HP ∟STATS(6)=2 ∟STATS(6)=5
Calculator A Calculator B
1SCREEN-A.gif 1SCREEN-B.gif

Final Notes

Whilst the abilities of the GetCalc( command make it harder to create multi-calculator programs, it certainly is not impossible. You just need to think extra hard and create very clever workarounds to its boundaries.

If you have any questions or comments about these routines please ask in the discussion area for this page.

References

  • James Kanjo came up with the "Multi-Calculator Core" code in his IM program, and also came up with the "turn by turn battle" code, including the function to make one calculator respond to another calculator's ENTER keypress

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/multiplayer


Validation of User Input

Validation is the process of evaluating user input to ensure it satisfies the specified requirements. Most programs just blindly accept any input that the user enters, assuming that it was entered in correctly and that it is valid. This is a dangerous assumption, because there is a great likelihood that somebody at some point will enter in bad input. When that finally happens, the program will crash when it tries to use the input. In order to ensure this doesn't happen, you should validate user input.

When validating user input, there are three main approaches you can take:

  • Stopping the program — This validation approach involves asking the user for input, and then checking to see if it is a bad input value; if it is, you then just stop the program with a Return or Stop. The idea is that there is no point continuing on to the rest of the program, since the input would only cause the program to crash or get messed up when the input finally gets used.
  • Keep asking for input — This validation approach involves placing your validation inside of a Repeat or While loop, and using a variable as a flag to indicate whether the input is valid or not. The idea is that after asking the user for input, you check to make sure it is not a bad input value; if it is, the bad input flag will be set, and input will be asked for again.
  • Make bad input valid — This validation approach involves asking the user for input, and then trying to filter out any bad parts of the input that might be present. You can make the filters as in depth as you want, but because there is almost an infinite number of things that a user can enter in, there is no way to cover everything. Ultimately, it comes down to knowing the user, and what they are likely to enter in.

How to Validate Variables

There are three main variable types that a user will be asked to input values for in a program: reals, lists, and strings. Each of these variables has their own set of standard validation considerations to check for, along with whatever additional considerations you have in your particular program.

Reals

When validating a real variable, the main things to check for are:

  • Is it within the appropriate range?
  • Is it not a complex number (i.e., there is no imaginary i part)?
  • Is it an integer (i.e., no fraction part)?
  • Is it positive (or zero, if appropriate)?

Testing for these four conditions is relatively easy, considering that there are built-in commands that will take care of it for you: relational operators, the imag( command, and the fPart( command. Generally, you should do the complex number check before the other three checks, because an imaginary part in a number can cause problems.

There's another problem that comes up with using Input specifically. If the input is for a real number A, the user might enter a list, which will be stored to ∟A instead. A simple way of fixing this problem is to store an invalid value to A to begin with, which will be dealt with if the user enters a list and doesn't change A. Many times, this is as simple as using DelVar.

For a simple example of validating a real number, imagine asking the user to specify how many rounds of a game they want to play. A For( loop is used as the main game loop, with the number of rounds being the upper boundary. Since the lower boundary is zero, we want the user to input a number greater than zero. In addition, a For( loop does not work with complex numbers, and we do not want to allow a fraction part because the number of rounds is used to calculate the scoring.

Here is what the validation code for our game might look like with each of the three different validation approaches:

:DelVar AClrHome
:Input "ROUNDS: ",A
:If imag(A
:Return
:If A<1 or fPart(A
:Return
:0→A
:Repeat Ans
:ClrHome
:Input "ROUNDS: ",A
:If not(imag(A
:not(A<1 or fPart(A
:End
:DelVar AClrHome
:Input "ROUNDS: ",A
:max(1,iPart(real(A→A

There are a couple things you should note. In the stopping the program code, we used the Return command to stop the program, instead of the Stop command. This is so that the program will work correctly with subprograms and assembly shells. We used the opposite commands in the making bad input valid code: iPart( instead of fPart( and real( instead of imag(. We are also using the max( command to make one the minimum value for the input.

Lists

When validating a list, the main things to check for are:

  • Is the list length within the appropriate range?
  • Does each list element pass the real validation?

Testing for the list length condition and each of the list elements involves using the built-in dim( command. You first check to see that the list length is acceptable, and then use the dim( command as the upper boundary in a For( loop to go over the list elements one at a time. Each element is validated just like a real variable.

For a simple example of validating a list, imagine you have a lottery game and you want the user to specify three numbers. We want the numbers to be between 1-100, as well as not having an imaginary or fraction part. Here is what the validation code for our game might look like with each of the three different validation approaches:

:ClrHome
:Input "NUMBERS: ",L1
:If 3≠dim(L1:Return
:For(I,1,3
:L1(I
:If imag(Ans:Return
:If Ans<1 or Ans>E2 or fPart(Ans
:Return
:End
:Repeat A=3
:ClrHome
:Input "NUMBERS: ",L1
:DelVar A
:For(I,1,3(3=dim(L1
:L1(I
:If not(imag(Ans
:A+not(Ans<1 or Ans>E2 or fPart(Ans→A
:End:End
:ClrHome
:Input "NUMBERS: ",L1
:For(I,1,3-dim(L1
:randInt(1,E2→L1(1+dim(L1
:End
:3→dim(L1
:max(1,min(E2,iPart(real(L1→L1

Like with the example from before, we had to check for the complex number before checking for the number boundaries and fraction part. This is because neither of those commands work with complex numbers; they will actually throw a ERR:DATA TYPE error. Also important is the optimization that we used to move the list dimension check into the For( loop's upper boundary. This allowed us to eliminate a conditional that we would have had to add.

Strings

When validating a string, the main things to check for are:

  • Is the string length within the appropriate range?
  • Does the string only contain the appropriate characters?

Testing for the string length involves using the built-in length( command. This check by itself is not enough, however, because a string treats commands and functions as just one character (i.e., a string of "ABOutput(" is considered to be three characters long). The way you resolve this problem is by making sure the string only contains certain characters. This involves creating a string of acceptable characters, and then checking the user input against it.

For a simple example of validating a string, imagine you have a two-player hangman game and you want the user to enter in an eight letter word, so that the other player can guess it. The only characters that are allowed are the uppercase alphabet (A-Z), and there is no restriction that the word has to actually exist. (Programming in a check for that would involve keeping a dictionary of words, and that could potentially take up a lot of memory.)

Here is what the validation code for our game might look like with each of the three different validation approaches:

:"ABCDEFGHIJKLMNOPQRSTUVWXYZ
:ClrHome
:Input "WORD: ",Str1
:If 8≠length(Str1:Return
:If not(min(seq(inString(Ans,sub(Str1,I,1)),I,1,8
:Return
:"ABCDEFGHIJKLMNOPQRSTUVWXYZ→Str0
:0:Repeat Ans
:ClrHome
:Input "WORD: ",Str1
:If 8=length(Str1
:min(seq(inString(Str0,sub(Str1,I,1)),I,1,8
:End
:"ABCDEFGHIJKLMNOPQRSTUVWXYZ→Str0
:ClrHome
:Input "WORD: ",Str1
:For(I,1,8-length(Str1
:Str1+sub(Str0,randInt(1,26),1→Str1
:End
:For(I,1,8
:If not(inString(Str0,sub(Str1,I,1
:sub(sub(" "+Str1,1,I)+sub(Str0,randInt(1,26),1)+sub(Str1+" ",I+1,9-I),2,8→Str1
:End

When the user inputs a word, we loop through all of the characters in the word and get their positions in our acceptable characters string. If any of the characters weren't in the string, then their position will be zero, and when we take the minimum of all the positions, the smallest will be zero. With the making bad input valid code, we also concatenate how ever many characters we need to make the word eight characters long.

Making Validation More Friendly

There are a couple different ways you can make validation more user-friendly: displaying error messages when there is bad input, and storing input as a string and converting it to the appropriate variable type.

Displaying error messages to the user when they enter bad input helps the user correct their mistake, and provides some direction on what input you are expecting them to enter. An error message does not need to be complicated or long — just enough so that you can get the point across. For example, say a program is a number guessing game, and the user is expected to enter in a number between 1-1000. If they enter 5000, you can display the message "Between 1-1000".

Storing input as a string allows you to accept any input that the user may enter, even if it is messed up, entered in in the wrong format, or inappropriate for the variable that you are storing it to. This way instead of the program crashing when it gets bad input, it can actually handle it and do whatever it needs to to make it work. You then just check to see if the string has the appropriate value(s), and convert it to the desired variable using the expr( command.

The validation for the real variable, for example, did not include a check for whether it is a list or string. This is because you can only really check for those things when you have a string that you can manipulate. If we wanted to add that check, we can search the string for an opening curly brace and commas or any characters besides numbers. If we find those things, we know that the input is bad, and we can reject it and ask for input again.

In the case of the real variable, the other advantage of using a string is that you don't have to worry about whether the calculator is storing the variable to a list. More specifically, if a list is entered for input, the Input and Prompt commands will actually store the input to a list with the same name. This is possible because you don't need to include the character when referring to a user-defined list. (Entering a string would also work, and the string would become associated with the list.)

Besides checking the list for whether it is a real variable or string, you also can check that it is in the appropriate format. When a list is entered, it needs to start with an opening curly brace, and then have each element separated by a comma. Because most users forget to include the opening curly brace, it is very convenient to place that at the beginning of the list yourself, so that the user never even knows about needing it.

You can take that idea even further, and allow a list to be entered in many different ways: with commas and curly brackets, with commas and no brackets, as a list name (L1 through L6), or as a name starting with ∟, or as a name without the ∟. Instead of requiring one of these, the program might very well be programmed to handle all of them. This all comes down to finding alternate ways of making user input valid.

Thoughts to Consider

The amount of validation you put in a program depends on how large and/or complicated the program is. If you have an extremely complex game with all sorts of user input, then it would be appropriate to include validation for some or most of those things. The general guideline is that the amount of validation needed correlates to the size of the game — i.e., a short math routine probably wouldn't need validation.

While discussing validation, it is also important to mention that since the Input and Prompt commands only work on the home screen, you need to write your own custom input routine using the getKey command if you want to get input on the graph screen. If your entire program is already on the graph screen, however, this should not be an issue, because it makes perfect sense to maintain the user's attention on the graph screen.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/validation


Recursion

Good programmers usually design their programs to utilize subprograms (calling another program from within the program) for optimization but another alternative that is available, but less often used, is the program simply calling itself — more commonly known as recursion.

The basic premise behind recursion is breaking up a problem into smaller problems, and then working your way through each problem until they are all completed. By tackling one small problem at a time, instead of the entire problem, the code needed is typically not only smaller and easier to understand (i.e., more manageable), but also tends to be faster.

However, recursion isn't always the most appropriate approach. You can usually rewrite a recursive program to use iteration instead (whether it's a While, Repeat, or For( loop). While the iteration code may be larger, it doesn't need the additional memory for each call that the program makes like recursion does. Iteration is also better when trying to implement an algorithm with recursion isn't very practical.

Problems with Recursion

There are some problems you will come across when trying to use recursion in your programs. Each of these problems is inherent to TI-Basic because of the way TI designed it, which means you can't change them. Fortunately, you can use some creative thinking to work around them.

The first problem you will come across is that you can only call a program a set number of times before you run out of memory and the program crashes — giving you the dreaded ERR:MEMORY error. The reason that this happens is because the calculator places each program call on a stack.

The program call stack is kept in RAM, so it is fine as long as its size doesn't exceed the amount of free RAM available. Each program call takes up approximately sixteen bytes, so just divide that by the free RAM to see how many program calls you can make.

Besides simply limiting the number of program calls you make in a program (i.e., trying to keep recursion to a minimum), a work around to this problem is storing a special value to a variable (something unique that wouldn't be entered by accident), displaying a message to the user telling them to "Press ENTER" and then stopping the program with the Return command after a set number of program calls have occurred.

:312958→A
:Output(4,4,"Press ENTER
:Return

Once the user presses ENTER, you will want to include a check at the beginning of the program for the variable you used to see if its value is equal to the unique value you assigned it. If it is, you then can jump to the place in the program where you left off before. You also want to give the variable a new value so that the program won't accidentally jump to the place in the program when the program is next executed.

:If A=312958  // Check if variable equal to unique value
:Goto A
...
:Lbl A
:1→A  // Reset variable to a new value

Another problem you will cross across is that TI-Basic programs don't have return values. In 68k TI-Basic (which is much more powerful overall), a return value can be passed to the calling program, which can then use it however they want (for example, to determine which course of action to take next).

While you can't add a return value to a program, you can mimic that functionality using a variable. The best variable to use is Ans because it can take on whatever value and variable type you want, so the program doesn't have a specific variable hard-coded in. This is especially important because variables are shared by every program.

Related to creating a return value is the problem of creating (pseudo) local variables. As you deal with each program call in recursion, it is useful to be able to keep track of variables and how they change from one program call to the next. While there are no local variables, you can make a list perform in that capacity.

In addition to the list itself, an index variable that keeps track of where you are in the list is also required. Whenever you enter a program that needs a local variable, increase the index variable and add a new element to the end of the list with augment(∟NAME,{var}). When you exit the program, decrease the index variable and remove the element from the list with var→dim(∟NAME). You can access the local variable at any time with ∟NAME(var).

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/recursion


Assembly

Besides TI-BASIC, assembly is the other primary programming language available for the TI-83 series calculators. Unlike TI-BASIC, which uses commands and functions that are easy to understand, assembly is programmed in the calculator's own machine language. Thus, it is much harder to program in and read.

This lack of usability, however, is more than made up for when you consider the fact that assembly is much faster and more feature rich than TI-BASIC. Games that normally can't be done (or, if they can be done, they aren't done very well) in TI-BASIC are just considered average in assembly.

At the same time, there aren't as many assembly programmers compared to TI-BASIC programmers; and subsequently, effort has been made to enhance TI-BASIC using assembly, to make it more capable of quality games and programs. This includes:

  • Shells — A shell allows a person to run a program from inside one central place, and since most assembly programs are run through a shell, it makes sense to run your TI-BASIC programs there as well.
  • Libraries — A library enhances a TI-BASIC program in some way, providing support to an internal function of the calculator (such as lowercase text) or access to a peripheral of the calculator (such as the USB port on the TI-84+/SE). If the ones available do not suit you, you can even make your own.
  • Applications — BASIC Builder allows you to package your TI-BASIC program(s) into a Flash application, which appears in the APPS menu and gets executed just like a regular assembly application.

The TI-BASIC language itself provides three commands — Asm(, AsmPrgm, and AsmComp( — for running and compiling shell-independent assembly programs, which you simply run from the home screen or inside a program. Writing these kinds of assembly programs is actually more difficult, however, because the assembly language instructions are represented as hexadecimal numbers. There are some short assembly programs that can be written on the calculator and be of great use to BASIC programmers.

Two additional commands for running assembly programs have been added on the TI-84 Plus and TI-84 Plus SE calculators: OpenLib( and ExecLib. They can be used for running routines from Flash application libraries that have been specifically written for use with these commands. So far, however, most major libraries use other methods, for compatibility with pre-TI-84 calculators. The only existing software that uses OpenLib( and ExecLib is usb8x, a library for advanced use of the TI-84 Plus/SE USB port. Here, compatibility is obviously out of the question.

(For more on assembly, visit z80 Heaven and WikiTI.)

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/assembly


The left() Command

left.png

Command Summary

Returns a subsection from the left of a list or string, or the left hand side of an equation.

Command Syntax

left(equation)
left(list-or-string,length)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 3 to enter the List submenu.
  • Press 9 to select left(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

When applied to a list or a string, left(x,length) gets the first length elements/characters of x. This is an alternative to mid(), which will do the same thing from any point in the list or string, not just the beginning.

When applied to an equation (such as x=5) or an inequality (such as x<3), left() returns the left-hand side of the equation. This only works for equations that don't get simplified: left(2+2=4) will not work, because 2+2=4 will return 'true' first.

:left({1,2,3,4,5},3)
           {1  2  3}
:left("TI-Basic Developer",8)
           "TI-Basic"
:left(x^2+2x+1>0)
           x^2+2*x+1
:left({1,2,3,4,5},0)
           {}

Optimization

Use left() instead of mid() when the substring starts at the beginning of the list or string.

Error Conditions

260 - Domain error happens when the argument is not a list, string, or equation, or is an equation that has simplified.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:left


The length( Command
LENGTH.GIF

Command Summary

Returns the length of a string.

Command Syntax

length(string)

Menu Location

This command can only be found in the catalog. Press:

  1. 2nd CATALOG to access the command catalog
  2. L to skip to commands starting with L
  3. scroll down to length( and select it

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

This command is used to determine the length of a string. Unlike the dim( command for lists and matrices, it cannot be used to change this length, as there is no null character for strings (the null value is 0 for lists and matrices).

:length("HELLO
    5

Keep in mind that the length is measured in the number of tokens, and not the number of letters in the string. For example, although the sin( command contains 4 characters ("s", "i", "n", and "("), it will only add 1 to the total length of a string it's in. The execution time for length( is directly proportional to the length of the string.

Advanced Uses

The code for looping over each character (technically, each token) of a string involves length(:

:For(N,1,length(Str1
...
use sub(Str1,N,1 for the Nth character
...
:End

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/length


The Line( Command
LINE.GIF

Command Summary

Draws a line at any angle.

Command Syntax

Line(X1,Y1,X2,Y2[,erase,color,style])

Menu Location

Press:

  1. 2nd DRAW to enter the draw menu
  2. 2 to insert the Line( token, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Line( command is used to draw lines at any angle, as opposed to only drawing vertical or horizontal lines. Line(X1,Y1,X2,Y2) will draw a line from (X1,Y1) to (X2,Y2). Line( is affected by the window settings, although you can use a friendly window so there is no impact on the command.

:Line(5,5,20,3)

Advanced Uses

Line has an optional fifth argument. It can be any real number, but the default is one. If the fifth argument, erase, is something other than 0, then it will simply draw the line. If erase is 0, then it will erase the line.

:Line(5,5,20,3,0)

Leave off the ending argument if you are just drawing the line.

:Line(5,5,20,3,1)
can be
:Line(5,5,20,3)

The ending argument can be a formula, which is useful for movement applications and other things such as health bars where the lines drawn are constantly different. The following draws or erases a line depending on whether a key is pressed.

:getKey
:Line(5,5,20,3,not(Ans

If working on a TI 84+CSE or TI 84+CE, then the fifth argument of the Line( command can be a color name or ID number:

:Line(5,5,20,3,BROWN

The last argument, line style, is an optional argument that chooses what style of line to draw on the color calculators.

1 pixel wide line
:Line(5,5,20,3,RED,1
2 pixel wide line
:Line(5,5,20,3,RED,2
shaded above
:Line(5,5,20,3,RED,3
shaded below
:Line(5,5,20,3,RED,4

Command Timings

If you are drawing horizontal or vertical lines that stretch the entire graph screen, such as a border, it is better to use Vertical or Horizontal. These are smaller and are usually faster as well.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/line


The LinReg(a+bx) Command

Command Summary

Calculates the best fit line through a set of points.

Command Syntax

LinReg(a+bx) [x-list, y-list, [frequency], [equation]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 8 to select LinReg(a+bx), or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The LinReg(a+bx) command is one of several that can calculate the line of best fit through a set of points (it differs from LinReg(ax+b) only in the format of its output). To use it, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points.

In its simplest form, LinReg(a+bx) takes no arguments, and calculates a best fit line through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:LinReg(a+bx)

On the home screen, or as the last line of a program, this will display the equation of the line of best fit: you'll be shown the format, y=a+bx, and the values of a and b. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a, b, r, and r² will be set as well. These latter two variables will be displayed only if "Diagnostic Mode" is turned on (see DiagnosticOn and DiagnosticOff).

You don't have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:LinReg(a+bx) ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the line of best fit is stored to this equation automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the line of best fit will be in terms of X anyway, this doesn't make much sense.

An example of LinReg(a+bx) with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:LinReg(a+bx) ∟FAT,∟CALS,∟FREQ,Y₁

Advanced Uses (for programmers)

LinReg(a+bx), along with LinReg(ax+b), can be used to convert a number to a string.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/linreg-a-bx


The LinReg(ax+b) Command

Command Summary

Calculates the best fit line through a set of points.

Command Syntax

LinReg(ax+b) [x-list, y-list, [frequency], [equation]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 4 to select LinReg(ax+b), or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The LinReg(ax+b) is one of several commands that can calculate the line of best fit through a set of points. To use it, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points.

In its simplest form, LinReg(ax+b) takes no arguments, and calculates a best fit line through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:LinReg(ax+b)

On the home screen, or as the last line of a program, this will display the equation of the line of best fit: you'll be shown the format, y=ax+b, and the values of a and b. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a, b, r, and r² will be set as well. These latter two variables will be displayed only if "Diagnostic Mode" is turned on (see DiagnosticOn and DiagnosticOff).

You don't have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:LinReg(ax+b) ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the line of best fit is stored to this equation automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the line of best fit will be in terms of X anyway, this doesn't make much sense.

An example of LinReg(ax+b) with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:LinReg(ax+b) ∟FAT,∟CALS,∟FREQ,Y₁

Advanced Uses (for programmers)

LinReg(ax+b), along with LinReg(a+bx), can be used to convert a number to a string.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/linreg-ax-b


The LinRegTInt Command

Command Summary

Calculates the linear regression of two sets of data with a confidence interval for the slope coefficient.

Command Syntax

LinRegTInt [x-list, y-list, [frequency], [confidence level], [equation]]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. RIGHT to access the TESTS submenu
  3. ALPHA G to select LinRegTInt, or use arrows

Calculator Compatibility

TI-84+(SE) OS 2.30 or greater

Token Size

2 bytes

Like LinReg(ax+b) and similar commands, LinRegTInt finds the best fit line through a set of points. However, LinRegTInt adds another method of checking the quality of the fit, by calculating a t confidence interval for the slope b. If the confidence interval calculated contains zero, the data supplied is insufficient to conclude a linear relation between the variables.

To use LinRegTInt, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points. You do not have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command.

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they are L₁ and L₂.

You can supply a confidence level probability as the fourth argument. It should be a real number between zero and one. If not supplied, the default value is .95. (95% confidence level) If you need to specify a different confidence level, you must enter the names of the lists as well, even if they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the line of best fit is stored to this equation automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last.

For example, both

:{4,5,6,7,8→L₁
:{1,2,3,3.5,4.5→L₂
:LinRegTInt

and

:{4,5,6,7,8→X
:{1,2,3,3.5,4.5→Y
:{1,1,1,1,1→FREQ
:LinRegTTest ∟X,∟Y,∟FREQ,.95,Y₁

will give the following output:

LinRegTInt
    y=a+bx
    (.69088,1.0091)
    b=.85
    df=3
    s=.158113883
    a=-2.3
    r²=.9897260274
    r=.9948497512

(the last two lines will only appear if diagnostics have been turned on - see DiagnosticOn)

  • The first line shows the confidence interval containing the slope of the fitted line; as mentioned above, if the interval contains 0, it cannot be concluded that the two variables have a linear relationship. Also, the smaller the difference between the two numbers, the more precision that can be attributed to the calculated slope.
  • df is the degrees of freedom, equal to the number of points minus two.
  • a and b are the parameters of the equation y=a+bx, the regression line we've calculated
  • s is the standard error about the line, a measure of the typical size of a residual (the numbers stored in ∟RESID). It is the square root of the sum of squares of the residuals divided by the degrees of freedom. Smaller values indicate that the points tend to be close to the fitted line, while large values indicate scattering.
  • r² and r are respectively the coefficients of determination and correlation: a value near 1 or -1 for the former, and near 1 for the latter, indicates a good fit.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/linregtint


The LinRegTTest Command
LINREGTTEST.GIF

Command Summary

Calculates the best fit line through a set of points, then uses a significance test on the slope of the line.

Command Syntax

LinRegTTest [x-list, y-list, [frequency], [alternative], [equation]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. RIGHT to access the TESTS submenu
  3. ALPHA E to select LinRegTTest, or use arrows

Change the last keypress to ALPHA F on a TI-84+/SE with OS 2.30 or higher.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

Like LinReg(ax+b) and similar commands, LinRegTTest finds the best fit line through a set of points. However, LinRegTTest adds another method of checking the quality of the fit, by performing a t-test on the slope, testing the null hypothesis that the slope of the true best fit line is 0 (which implies the absence of correlation between the two variables, since a relation with a slope of zero means the x-variable does not affect the y-variable at all). If the p-value of the test is not low enough, then there is not enough data to assume a linear relation between the variables.

To use LinRegTTest, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points.

In its simplest form, LinRegTTest takes no arguments, and calculates a best fit line through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:LinRegTTest

The output will look as follows:
LinRegTTest
 y=a+bx
 β≠0 and ρ≠0
 t=53.71561274
 p=4.2285344e-8
 df=5
 a=145.3808831
 b=13.09073265
 s=5.913823968
 r²=.9982701159
 r=.9991346836

(the last two lines will only appear if diagnostics have been turned on - see DiagnosticOn)
  • β and ρ: this line represents the alternative hypothesis. β is the true value of the statistic b (it is what we would get if the regression was done on the entire population, rather than a sample); ρ is the true value of the statistic r.
  • t is the test statistic, used to calculate p.
  • p is the probability that we'd get a correlation this strong by chance, assuming the null hypothesis that there is no actual correlation. When it's low, as here, this is evidence against the null hypothesis. Since p<.01, the data is significant on a 1% level, so we reject the null hypothesis and conclude that there is a correlation.
  • df is the degrees of freedom, equal to the number of points minus two
  • a and b are the parameters of the equation y=a+bx, the regression line we've calculated
  • s is the standard error about the line, a measure of the typical size of a residual (the numbers stored in ∟RESID). It is the square root of the sum of squares of the residuals divided by the degrees of freedom. Smaller values indicate that the points tend to be close to the fitted line, while large values indicate scattering.
  • r² and r are respectively the coefficients of determination and correlation: a value near 1 or -1 for the former, and near 1 for the latter, indicates a good fit.

You do not have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:LinRegTTest ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they are L₁ and L₂.

You can add the alternative argument to change the alternative hypothesis from the default (β≠0 and ρ≠0). This is used when you have prior knowledge either that a negative relation is impossible, or that a positive one is impossible. The values of the alternative argument are as follows:

  • negative: the alternative hypothesis is β<0 and ρ<0 (we have prior knowledge that there can be no positive relation)
  • 0: the alternative hypothesis is β≠0 and ρ≠0 (we have no prior knowledge)
  • positive: the alternative hypothesis is β>0 and ρ>0 (we have prior knowledge that there can be no negative relation)

Obviously, if you want the alternative hypothesis to be β≠0 and ρ≠0, the default, you don't need to supply this argument. However, if you do, you must enter the names of the lists as well, even if they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the line of best fit is stored to this equation automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the line of best fit will be in terms of X anyway, this doesn't make much sense.

An example of LinRegTTest with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:LinRegTTest ∟FAT,∟CALS,∟FREQ,1,Y₁

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/linregttest


The List►matr( Command
LISTTOMATR.GIF

Command Summary

Builds a matrix from one or more lists.

Command Syntax

List►matr(list1, [list2, …], matrix

Menu Location

Press:

  1. MATRX (on the 83) or 2nd MATRX (83+ or higher) to access the matrix menu
  2. LEFT to access the MATH submenu
  3. 9 to select List►matr(, or use arrows.

Alternatively, press:

  1. 2nd LIST to access the list menu
  2. LEFT to access the OPS submenu
  3. 0 to select List►matr(, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The List►matr( builds a matrix by combining several list expressions, and stores it to the specified variable ([A] through [J]). Each list specifies a column of the matrix: the first list will be stored down the first (leftmost) column, the second list down the second column, and so on. For example:

List►matr({1,2,3},{10,20,30},{100,200,300},[A]
        Done
[A]
        [[1 10 100]
         [2 20 200]
         [3 30 300]]

Advanced Uses

The calculator can actually handle lists that are not the same size. It will pad zeroes to the shorter lists, until they have the same length as the longest list.

List►matr({1,2,3},{10},{100,200},[A]
        Done
[A]
        [[1 10 100]
         [2  0 200]
         [3  0   0]]

Error Conditions

  • ERR:ARGUMENT is thrown if there are more than 99 lists (since a matrix can be at most 99x99)
  • ERR:INVALID DIM is thrown if one of the lists is longer than 99 elements (since a matrix can be at most 99x99)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/list-matr


The ln( Command
LN.GIF

Command Summary

Computes the (principal branch of the) natural logarithm.

Command Syntax

ln(value)

Menu Location

Press the LN key to paste ln(.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ln( command computes the natural logarithm of a value — the exponent to which the constant e must be raised, to get that value. This makes it the inverse of the e^( command.

ln( is a real number for all positive real values. For negative numbers, ln( is an imaginary number (so taking ln( of a negative number will cause ERR:NONREAL ANS to be thrown in Real mode), and of course it's a complex number for complex values. ln( is not defined at 0, even if you're in a complex mode.

Advanced Uses

Using either the ln( or the log( command, logarithms of any base can be calculated, using the identity:

(1)
\begin{align} \log_b{x} = \frac{\ln{x}}{\ln{b}} = \frac{\log{x}}{\log{b}} \end{align}

So, to take the base B log of a number X, you could use either of the following equivalent ways:

:log(X)/log(B)
:ln(X)/ln(B)

This is the exponent to which B must be raised, to get X.

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/ln


The LnReg Command
LNREG.GIF

Command Summary

Calculates the best fit logarithmic curve through a set of points.

Command Syntax

LnReg [x-list, y-list, [frequency], [equation]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 9 to select LnReg, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

LnReg tries to fit a logarithmic curve (y=a+b*lnx) through a set of points. To use it, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points.

The calculator does this regression by taking the natural log ln( of the x-coordinates (this isn't stored anywhere) and then doing a linear regression. This means that if any x-coordinates are negative or 0, the calculator will instantly quit with ERR:DOMAIN.

In its simplest form, LnReg takes no arguments, and fits a logarithmic curve through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:LnReg

On the home screen, or as the last line of a program, this will display the equation of the curve: you'll be shown the format, y=a+b*ln(x), and the values of a and b. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a, b, r, and r² will be set as well. These latter two variables will be displayed only if "Diagnostic Mode" is turned on (see DiagnosticOn and DiagnosticOff).

You don't have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:LnReg ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the curve's equation is stored to this variable automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the equation will be in terms of X anyway, this doesn't make much sense.

An example of LnReg with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:LnReg ∟FAT,∟CALS,∟FREQ,Y₁

Error Conditions

  • ERR:DOMAIN is thrown if any x-coordinates are negative or 0.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/lnreg


The Local Command

local.png

Command Summary

Declares variables to be local to the current function or program.

Command Syntax

Local var1[,var2,…]

Menu Location

Starting in the program editor:

  • Press F4 to enter the Var menu.
  • Press 3 to select Local.

Calculator Compatibility

This command works on all calculators.

Token Size

3 bytes

The Local command declares one or more variables to be local to the function or program it's used in. This means that the program "owns" these variables, so to speak: their values start out undefined, no matter if a variable with the same name was defined outside the program, and the variables will be cleaned up once the program exits. Even subprograms called from the main program can't see the main program's local variables.

Local is useful to avoid leaving lots of variables behind, but you could do that by deleting them as well. More importantly, it assures that you won't overwrite any already existing variables. Finally, local variables are the only ones a function can use.

You may get a few local variables for free, without the Local command: these are the parameters to a function or program. For example, if you define the function f(x), you can modify x all you like without the fear of changing any variables outside the function.

Advanced Uses

The interaction of Local with expr() is somewhat bizarre. In a way, expr() is a subprogram, so it can't see the local variables of the program that created it. This is a problem with output: for instance, expr("Disp x") will not work properly if x is a local variable.

In many cases, this doesn't matter: for instance, expr("x^2") may not be able to access the value of x if x is local, but it will return the symbolic value x^2, which will later be simplified in the main program. Things change if there's already a global variable called x defined. In that case, expr("x^2") will not find the local value of x, but it will see the global variable instead, so it will evaluate x^2 based on that value. This isn't usually what you want. But it does give you a way to access global variables: expr("x") refers to the global variable x if there is one, and the local variable otherwise.

Error Conditions

550 - Invalid outside function or program happens when Local is used outside a function or program.

610 - Invalid variable name in a Local statement happens when making a system variable local.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:local


The log( Command
LOG.GIF

Command Summary

Computes the (principal branch of the) base 10 logarithm.

Command Syntax

log(value)

Menu Location

Press the LOG key to paste log(.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The log( command computes the base 10 logarithm of a value — the exponent to which 10 must be raised, to get that value. This makes it the inverse of the 10^( command.

log( is a real number for all positive real values. For negative numbers, log( is an imaginary number (so taking log( of a negative number will cause ERR:NONREAL ANS to be thrown in Real mode), and of course it's a complex number for complex values. log( is not defined at 0, even if you're in a complex mode.

Advanced Uses

Using either the ln( or the log( command, logarithms of any base can be calculated, using the identity:

(1)
\begin{align} \log_b{x} = \frac{\ln{x}}{\ln{b}} = \frac{\log{x}}{\log{b}} \end{align}

So, to take the base B log of a number X, you could use either of the following equivalent ways:

:log(X)/log(B)
:ln(X)/ln(B)

This is the exponent to which B must be raised, to get X.

The base 10 logarithm specifically can be used to calculate the number of digits a whole number has:

:1+int(log(N))

This will return the number of digits N has, if N is a whole number. If N is a decimal, it will ignore the decimal digits of N.

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/log


The Logistic Command
LOGISTIC.GIF

Command Summary

Calculates the least-squares best fit logistic curve through a set of points.

Command Syntax

Logistic [x-list, y-list, [frequency], [equation]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. ALPHA B to select Logistic, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

Logistic tries to fit a logistic curve (y=c/(1+a*e-b*x)) through a set of points. To use it, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the ith element of one list matches up with the ith element of the other list. L₁ and L₂ are the default lists used, and the List Editor (STAT > Edit…) is a useful window for entering the points.

The explanation for the odd format of a logistic curve is that it is the solution to a differential equation that models population growth with a limiting factor: a population that grows according to a logistic curve will start out growing exponentially, but will slow down before reaching a carrying capacity and approach this critical value without reaching it. The logistic curve also has applications, for example, in physics.

In its simplest form, Logistic takes no arguments, and fits a logistic curve through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:Logistic

On the home screen, or as the last line of a program, this will display the equation of the curve: you'll be shown the format, y=c/(1+ae^(-bx)), and the values of a, b and c. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a, b, and c will be set as well. There are no correlation statistics available for Logistic even if Diagnostic Mode is turned on (see DiagnosticOn and DiagnosticOff).

You do not have to do the regression on L₁ and L₂, in which case you will have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:Logistic ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the curve's equation is stored to this variable automatically. This does not require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the equation will be in terms of X anyway, this doesn't make much sense.

An example of Logistic with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:Logistic ∟FAT,∟CALS,∟FREQ,Y₁

Warning: if your data is not even slightly logistic in nature, then the calculator may return an error such as ERR:OVERFLOW. This happens when the calculator tries to calculate a carrying capacity, c, for the data, but since the rate of change in data doesn't seem to be slowing down, it assumes that the carrying capacity is still very far off, and tries large values for it. These values may get so large as to cause an overflow.

The Levenberg-Marquardt nonlinear least-squares algorithm is used by Logistic.

Error Conditions

  • ERR:ARGUMENT is thrown by using only one list.
  • ERR:DIM MISMATCH is thrown if the dimensions of two lists do not match.
  • ERR:DOMAIN is thrown if Logistic is left without using lists or enough instructions.
  • ERR:DATA TYPE is thrown if lists are not used, or a list contains a number like "4i".

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/logistic


The Loop Command

loop.png

Command Summary

Repeats a block of code forever.

Command Syntax

:Loop
(block of code)
:EndLoop

Menu Location

Starting in the program editor:

  • Press F2 to enter the Control menu.
  • Press 6 to paste Loop..EndLoop.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes for Loop;
4 bytes for EndLoop.

A Loop..EndLoop block is used to make the code inside the Loop repeat forever. For example, the following code will keep printing "Hello!" until you break out of the program with the ON key or the calculator runs out of batteries:

:Loop
: Disp "Hello!"
:EndLoop
           Hello!
           Hello!
           Hello!
           ...

Generally, Loop isn't used just like that, because having to end a program with the ON key lacks style. There are two ways to break out of the loop:

  • using Goto, you can jump to somewhere else in the program.
  • using Exit, you can exit the loop, continuing the program immediately after the EndLoop command.

Generally, using Exit is considered more stylish — and it's easier to read the code, because you don't have to search the entire program for the Goto's matching label.

Error Conditions

730 - Missing start or end of block syntax happens when the Loop is missing an EndLoop, or vice versa.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:loop


The Manual-Fit Command
SCREEN02.BMP

Command Summary

Allows user to create a line of best fit and modify it

Command Syntax

Manual-Fit {Function}

Menu Location

Under Statistics or Catalog

  1. Press STAT
  2. Go to CALC
  3. Press ALPHA D (or scroll to bottom)

Calculator Compatibility

TI-84+/SE (OS 2.30 or greater)

Token Size

2 bytes

This command will allow the user to create a line of best fit according to their judgment. Activate the command by just pasting it on the screen. Then, click on a point for the line to begin followed by an end point. The calculator will then draw your line and display its equation at the top left corner of the screen. You can modify it by selecting the equation part and pressing enter. Input your desired value for the calculator to change it. The equation is stored into Y₁. If you specify what equation you want to store it to, then it will store to that function.

:Manual-Fit
(this activates the command and stores to Y₁
:Manual-Fit Y₃
(this stores to Y₃ instead)

One note about this is that it only graphs linear models. It is written in the form y=mx+b, and you can modify m or b.
Exit out by 2nd QUIT.

Advanced Uses

This command is able to function in a program, but you cannot modify the values. This is a unique form of gathering user input that stores into the specified Y= function. Of course, this draws a line across the graph screen. You can then convert the function into a different form, like this:

:Manual-Fit
:Equ▶String(Y₁,Str1

This will turn the equation the user drew into a string which can then be used for output or calculations.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/manual-fit


The MATHPRINT Command

Command Summary

Mode command that puts the calculator into Classic mode.

Command Syntax

MATHPRINT

Menu Location

Press:

  1. MODE
  2. DOWN until you reach Mathprint or Classic
  3. ENTER on Mathprint

Alternatively, use the catalog.

Calculator Compatibility

TI-84 2.53MP or later

Token Size

2 bytes

MATHPRINT will put the calculator into Mathprint mode as opposed to Classic mode. In MathPrint mode, enhanced homescreen input formatting is available. The Classic mode will make the calculator display everything as a calculator of lower OS would, including input. For instance, rather than superscripting exponents as Mathprint mode would, Classic mode uses the simple caret syntax (^).

Mathprint mode:
24
     16

Classic mode:
2^4
     16

When in Mathprint mode, text and numbers are displayed much slower than classic on the home screen and the function menus load slower. This can be inconvenient in games that use the home screen, but can also make solving equations that involve fractions and exponents easier as the numbers are in their correct positions and are the appropriate size.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/mathprint-mode


The Matr►list( Command
MATRTOLIST.GIF

Command Summary

Stores one or more columns of a given matrix to list variables

Command Syntax

Matr►list(matrix, list-var1, [list-var2, …])
Matr►list(matrix, column#, list-var)

Menu Location

Press:

  1. MATRX (on the 83) or 2nd MATRX (83+ or higher) to access the matrix menu
  2. LEFT to access the MATH submenu
  3. 8 to select Matr►list(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The Matr►list( command stores one or more columns of a matrix (or expression resulting in a matrix) to list variables. The syntax is simple: first enter the matrix, then enter the list or lists you want to store columns to. The first (leftmost) column will be stored to the first list entered, the second column will be stored to the second list, and so on. For example:

[[11,12,13,14][21,22,23,24][31,32,33,34
        [[11 12 13 14]
         [21 22 23 24]
         [31 32 33 34]]
Matr►list(Ans,L1,L2
        Done
L1
        {11 21 31}
L2
        {12 22 32}

If there are more lists than columns in the matrix when doing Matr►list(, the extra lists will be ignored.

Matr►list( can also be used to extract a specific column of a matrix to a list. The order of the arguments is: matrix, column number, list name.

[[11,12,13,14][21,22,23,24][31,32,33,34
        [[11 12 13 14]
         [21 22 23 24]
         [31 32 33 34]]
Matr►list(Ans,4,L1
        Done
L1
        {14 24 34}

Advanced Uses

While the command deals with columns, occasionally you might want to store the matrix to lists by rows. The T (transpose) command is your friend here: applying it to the matrix will flip it diagonally, so that all rows will become columns and vice-versa. For example:

[[11,12,13,14][21,22,23,24][31,32,33,34
         [[11 12 13 14]
         [21 22 23 24]
         [31 32 33 34]]
Matr►list(AnsT,L1,L2
         Done
L1
         {11 12 13 14}
L2
         {21 22 23 24}

Optimizations

When using Matr►list( to store to named lists, only the first list must have an ∟ in front of its name — it can be omitted for the rest. For example:

:Matr►list([A],∟COL1,∟COL2,∟COL3
can be
:Matr►list([A],∟COL1,COL2,COL3

On the other hand, when storing a specific column of a matrix to a named list, the list does not need to be preceded by an ∟.

:Matr►list([A],N,∟COL1
can be
:Matr►list([A],N,COL1

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/matr-list


The max( Command
MAX.GIF

Command Summary

Returns the maximum of two elements or of a list.

Command Syntax

  • for two numbers: max(x,y)
  • for a list: max(list)
  • comparing a number to each element of a list: max(x,list) or max(list,x)
  • pairwise comparing two lists: max(list1,list2)

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT to access the NUM submenu.
  3. 7 to select max(, or use arrows.

Alternatively, press:

  1. 2nd LIST to access the list menu.
  2. LEFT to access the MATH submenu.
  3. 2 to select max(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

max(x,y) returns the largest of the two numbers x and y. max(list) returns the largest element of list. max(list1,list2) returns the pairwise maxima of the two lists. max(list1,x) (equivalently, max(x,list1)) returns a list whose elements are the larger of x or the corresponding element of the original list.

max(2,3)
     3
max({2,3,4})
     4
max({1,3},{4,2})
     {4 3}
max({1,3},2)
     {2 3}

Unlike comparison operators such as < and >, max( can also compare complex numbers. To do this, both arguments must be complex — either complex numbers or complex lists: max(2,i) will throw an error even though max(2+0i,i) won't. In the case of complex numbers, the number with the largest absolute value will be returned. When the two numbers have the same absolute value, the first one will be returned: max(i,-i) returns i and max(-i,i) returns -i.

Advanced Uses

max( can be used in Boolean comparisons to see if at least one of a list is 1 (true) — useful because commands like If or While only deal with numbers, and not lists, but comparisons like L1=L2 return a list of values. In general, the behavior you want varies, and you will use the min( function or the max( function accordingly.

Using max( will give you a lenient test — if any one element of the list is 1 (true), then the max( of the list is true — this is equivalent to putting an 'or' in between every element. For example, this tests if K is equal to any of 24, 25, 26, or 34 (the getKey arrow key values):

:If max(K={24,25,26,34
:Disp "ARROW KEY

To get the element of a real list with the greatest absolute value, use imag(max(iAns.

Error Conditions

  • ERR:DATA TYPE is thrown when comparing a real and a complex number. This can be avoided by adding +0i to the real number (or i^4 right after it, for those who are familiar with complex numbers)
  • ERR:DIM MISMATCH is thrown, when using max( with two lists, if they have different dimensions.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/max


The mean( Command
MEAN.GIF

Command Summary

Finds the mean (the average) of a list.

Command Syntax

mean(list,[freqlist])

Menu Location

Press:

  1. 2ND LIST to enter the LIST menu.
  2. LEFT to enter the MATH submenu.
  3. 3 to select mean(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The mean( command finds the mean, or the average, of a list. It's pretty elementary. It takes a list of real numbers as a parameter. For example:

:Prompt L1
:Disp "MEAN OF L1",mean(L1

That's not all, however. Awesome as the mean( command is, it can also take a frequency list argument, for situations when your elements occur more than once. For example:

:Disp mean({1,2,3},{5,4,4})

is short for

:mean({1,1,1,1,1,2,2,2,2,3,3,3,3})

The frequency list {5,4,4} means that the first element, 1, occurs 5 times, the second element, 2, occurs 4 times, and the third element, 3, occurs 4 times.

Advanced Uses

You can also use the frequency list version of mean( to calculate weighted averages. For example, suppose you're trying to average grades in a class where homework is worth 50%, quizzes 20%, and tests 30%. You have a 90% average on homework, 75% on quizzes (didn't study too well), but 95% average on tests. You can now calculate your grade with the mean( command:

:mean({90,75,95},{50,20,30

You should get a 88.5 if you did everything right.

Frequency lists don't need to be whole numbers. Amazing as that may sound, your calculator can handle being told that one element of the list occurs 1/3 of a time, and another occurs 22.7 times. It can even handle a frequency of 0 - it will just ignore that element, as though it weren't there. In particular, mean(L1,L2) is effectively equivalent to sum (L1*L2)/sum(L2).

One caveat, though - if all of the elements occur 0 times, there's nothing to take an average of and your calculator will throw an error.

Error Conditions

  • ERR:DATA TYPE is thrown, among other cases, if the data list is complex, or if the frequencies are not all positive and real.
  • ERR:DIM MISMATCH is thrown if the frequency list and the data list have a different number of elements.
  • ERR:DIVIDE BY 0 is thrown if the frequency list's elements are all 0.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/mean


The median( Command
MEDIAN.GIF

Command Summary

Finds the median of a list.

Command Syntax

median(list,[freqlist])

Menu Location

Press:

  1. 2ND LIST to enter the LIST menu.
  2. LEFT to enter the MATH submenu.
  3. 4 to select median(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The median( command finds the median of a list. It takes a list of real numbers as a parameter. For example:

:Prompt L1
:Disp "MEDIAN OF L1",median(L1

That's not all, however. Awesome as the median( command is, it can also take a frequency list argument, for situations when your elements occur more than once. For example:

:Disp median({1,2,3},{5,4,4})

is short for

:median({1,1,1,1,1,2,2,2,2,3,3,3,3})

The frequency list {5,4,4} means that the first element, 1, occurs 5 times, the second element, 2, occurs 4 times, and the third element, 3, occurs 4 times.

Advanced Uses

Frequency lists don't need to be whole numbers. Amazing as that may sound, your calculator can handle being told that one element of the list occurs 1/3 of a time, and another occurs 22.7 times. It can even handle a frequency of 0 - it will just ignore that element, as though it weren't there. One caveat, though - if all of the elements occur 0 times, there's nothing to take the median of and your calculator will throw an error.

Error Conditions

  • ERR:DATA TYPE is thrown, among other cases, if the data list is complex, or if the frequencies are not all positive and real.
  • ERR:DIM MISMATCH is thrown if the frequency list and the data list have a different number of elements.
  • ERR:DIVIDE BY 0 is thrown if the frequency list's elements are all 0.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/median


The Med-Med Command
MED-MED.GIF

Command Summary

Calculates the median fit line through a set of points.

Command Syntax

Med-Med [x-list, y-list, [frequency], [equation]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 3 to select Med-Med, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Med-Med command is one of several that can calculate a line of best fit through a set of points. However, unlike the LinReg(ax+b) and LinReg(a+bx) commands, which generate the same result in different formats, Med-Med produces a different line entirely, known as the 'median fit line' or the 'median-median model'. This model is more resistant to outliers than the best-fit line produced by LinReg(ax+b)-type commands, in much the same way that the median of a set of data is more resistant to outliers than the mean. The process of calculating a median fit line is roughly as follows (reference):

  1. Divide the data into three equal groups by their x-values (the smallest third, the middle third, and the largest third)
  2. Find the "median point" for each group by pairing the median x-value in the group with the median y-value (this need not be an actual data point).
  3. These points are stored to (x₁,y₁), (x₂,y₂), and (x₃,y₃) on the calculator.
  4. Find the line passing through the median point for the first and third group.
  5. Shift this line one-third of the way toward the median point of the second group.

To use the Med-Med command, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points. As you can see from the steps shown above, Med-Med requires at least three points with different x-values to work with.

In its simplest form, Med-Med takes no arguments, and calculates a regression line through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:Med-Med

On the home screen, or as the last line of a program, this will display the equation of the regression line: you'll be shown the format, y=ax+b, and the values of a and b. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a and b will be set as well. There are no diagnostics available for the Med-Med command, so r and r² will not be calculated or displayed even if you run DiagnosticOn.

You don't have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:Med-Med ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the line of best fit is stored to this equation automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the line of best fit will be in terms of X anyway, this doesn't make much sense.

An example of Med-Med with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:Med-Med ∟FAT,∟CALS,∟FREQ,Y₁

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/med-med


The Menu( Command
MENU_ANIMATED.gif

Command Summary

Displays a generic menu on the home screen, with up to seven (or nine on color calculators) options for the user to select.

Command Syntax

Menu("Title","Option 1",Label 1[,…,"Option 7",Label 7])

Menu Location

While editing a program, press:

  1. PRGM to enter the PRGM menu
  2. Press ALPHA PRGM to choose Menu( or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

Menus are used for organization, to provide a list of choices for the user to select from, as well as a good way for users to interact with and navigate programs. Although using the Menu( command requires branching (which is generally frowned upon in most circumstances), the menu looks like a generic built-in menu, so it is familiar and easy to use for the user.

When the Menu( command is encountered during a program, the menu screen is displayed with the specified menu title in white-on-black text on the top line and each menu item listed below on its own line, the pause indicator turns on, and execution pauses until the user selects a menu item. There is a cursor that the user can move up and down the menu to select a menu item.

The menu title can be 16 characters or less on monochrome calculators (because of the screen width), and 26 characters or less on color calculators, and must be enclosed in a pair of quotation marks. The menu title looks best if you center it on the screen (using spaces to fill in the rest of the line), so that the entire top line will be highlighted. The menu can have up to seven menu items on monochrome and up to nine on color calculators (because of the screen height and the menu title on top).

After the menu title, you put a comma and then the menu items. There are two parts to a menu item: the text that will be displayed on the screen and the label that program execution will continue at if the user presses ENTER on the menu item or presses its corresponding number. The text can be fourteen characters or less on monochrome and 24 or less on color (because the menu item number is displayed on the left) and must be enclosed in a pair of quotation marks, and you have to separate the text and label with a comma.

PROGRAM:MENU
:Lbl NY
:Menu(" Select A Place ","NY",NY,"LA",NY,"MN",MN
:Lbl MN
:Disp "Good Choice!

Advanced Uses

When a program needs more than seven (or nine on color calculators) menu items, you will have to create another menu and then link to that menu from the first menu with one of the menu items. Similarly, you can also have two menu items go to the same label (you do not need two labels if they are right next to each other).

If you get tired of using the Menu( command every time you want to make a menu, the alternative is to make your own custom menu. A custom menu provides a richer experience for the user, and isn't much more work than using the Menu( command. In addition, as you get more experienced as a programmer, you'll come to enjoy using custom menus.

You can use a string variable for the menu title and menu item text instead of the text in quotes, which may sometimes be smaller if the text is used at other places in the program. Similarly, its possible to place all the menu titles in one string variable, and then just access the respective menu title as a substring Unfortunately, variables will not work for the menu item labels. You can also leave the menu title blank to give the illusion that there is no menu title by using two quotes side by side (i.e. "").

For many programs, including text-based programs (where menus are heavily used), there is a main menu that is used for navigating to the different parts of the program. While each program's main menu is unique, two of the most standard menu items on a main menu are Start and Quit — Start goes to the beginning of the program, while Quit goes to the end. It is also fairly common to place a label right before the main menu, so you can return to it again later in the program.

Problems

1. There is only one line for the title.
2. There are only seven (or nine on color calculators) slots for the menu items and no scrolling (you CAN add a "next" at the bottom, but that just looks bad, especially if you have a "back" and/or "exit" down there already)
3. The screen refreshes or blinks when you press down at the bottom to go back to the top.
4. During the loading of the menu, you can see what is written on the home screen.

Optimization

Because the Menu( command displays the menu screen instead of clearing the home screen, you do not need to put the ClrHome command before it.

:ClrHome
:Menu("Choose","Right",1,"Wrong",2
Remove ClrHome
:Menu("Choose","Right",1,"Wrong",2

Error Conditions

  • ERR:INVALID occurs if this statement is used outside a program.
  • ERR:LABEL is thrown when an option is chosen whose label doesn't exist.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/menu


The mid() Command

mid.png

Command Summary

Selects a substring from a string, or a sublist from a list.

Command Syntax

mid(string-or-list,start[,count])

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press D to enter the String submenu.
  • Press 5 to paste mid(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The mid() command can be used in two ways: to select a sublist from a list, or a substring from a string. In both cases, the syntax is similar:

  • the first argument is the list or string to start with.
  • the second argument is the number of the first element or character to include,
  • the third argument is how long the sublist or substring should be.

That is, mid(list,x,y) will give a list of the xth element, (x+1)th element, and so on up to the (x+y-1)th element of list. If x=2 and y=3, this will give a 3-element list starting from the 2nd element.

:mid({1,2,3,4,5},2,3)
    {2 3 4}

For strings, mid(string,x,y) will give a y-character-long string starting from the xth character of string:
:mid("TI-Basic",2,5)
    "I-Bas"

In practice, the mid() command is rarely useful for lists, although it might occasionally come in handy. It really shines with strings, since there is no other way to select a character from within a string. Whereas you might use list[5] to select the 5th element of a list, with a string you have to write mid(string,5,1) to get that single character.

A noteworthy feature of mid() is that out-of-bounds indices don't cause an error. If the length you give for the substring or sublist is more than the number of remaining characters or elements, then it will give you as many as there are, instead. If the value of start happens to be past the end, then the output will be a null value: the empty list {} for a list, and the empty string "" for a string.

Optimization

The third argument — the length of the sublist or substring — is optional if you want to include everything past the first element or character. For example:

:mid({1,2,3,4,5},3)
    {3 4 5}
:mid("TI-Basic",4)
    "Basic"

In this case, the result is the same as the result of right(), but the input is different.

Furthermore, if you're always going to start at the beginning of the string, left() is a better alternative to mid(): left(var,x) is equivalent to mid(var,1,x), and saves you a total of 3 bytes.

:mid(str,1,5)
    can be
:left(str,5)

Error Conditions

260 - Domain error happens when start isn't positive, or count is negative.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:mid


The min( Command
MIN.GIF

Command Summary

Returns the minimum of two elements or of a list.

Command Syntax

  • for two numbers: min(x,y)
  • for a list: min(list)
  • comparing a number to each element of a list: min(x,list) or min(list,x)
  • pairwise comparing two lists: min(list1,list2)

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT to access the NUM submenu.
  3. 6 to select min(, or use arrows.

Alternatively, press:

  1. 2nd LIST to access the list menu.
  2. LEFT to access the MATH submenu.
  3. ENTER to select min(.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

min(x,y) returns the smallest of the two numbers x and y. min(list) returns the smallest element of list. min(list1,list2) returns the pairwise minima of the two lists. min(list1,x) (equivalently, min(x,list1)) returns a list whose elements are the smaller of x or the corresponding element of the original list.

min(2,3)
     2
min({2,3,4})
     2
min({1,3},{4,2})
     {1 2}
min({1,3},2)
     {1 2}

Unlike relational operators, such as < and >, min( can also compare complex numbers. To do this, both arguments must be complex — either complex numbers or complex lists: min(2,i) will throw a ERR:DATA TYPE error even though min(2+0i,i) won't. In the case of complex numbers, the number with the smallest absolute value will be returned. When the two numbers have the same absolute value, the second one will be returned: min(i,-i) returns -i and min(-i,i) returns i.

Advanced Uses

min( can be used in Boolean comparisons to see if every value of a list is 1 (true) — useful because commands like If or While only deal with numbers, and not lists, but comparisons like L1=L2 return a list of values. In general, the behavior you want varies, and you will use the min( or max( functions accordingly.

Using min( will give you a strict test — only if every single value of a list is true will min( return true. For example, the following code will test if two lists are identical — they have the same exact elements — and print EQUAL in that case:

:If dim(L1)=dim(L2
:Then
:If min(L1=L2
:Disp "EQUAL
:End

The first check, to see if the sizes are identical, is necessary because otherwise comparing the lists will return a ERR:DIM MISMATCH error.

Error Conditions

  • ERR:DATA TYPE is thrown when comparing a real and a complex number. This can be avoided by adding 0i to the real number.
  • ERR:DIM MISMATCH is thrown, when using min( with two lists, if they have different dimensions.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/min


The nCr Command
NCR.GIF

Command Summary

Calculates the combinatorial number of combinations.

Command Syntax

a nCr b

Menu Location

Press:

  1. MATH to access the math menu.
  2. LEFT to access the PRB submenu.
  3. 3 to select nCr, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

nCr is the number of combinations function (or binomial coefficient), defined as a nCr b = a!/(b!*(a-b)!), where a and b are nonnegative integers. The function also works on lists.

Tip: nCr has a higher priority in evaluation than operators such as + or *: for example, 5X nCr 10 will be interpreted as 5(X nCr 10) and not as (5X) nCr 10. You might wish to use parentheses around complex expressions that you will give to nCr as arguments.

6 nCr 4
     15

The combinatorial interpretation of a nCr b is the number of ways to choose b objects, out of a total of a, if order doesn't matter. For example, if there 10 possible pizza toppings, there are 10 nCr 3 ways to choose a 3-topping pizza.

Error Conditions

  • ERR:DIM MISMATCH is thrown when applying nCr to two lists that have different dimensions.
  • ERR:DOMAIN is thrown for negative integers or decimals.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/ncr


The nDeriv( Command
NDERIV.GIF

Command Summary

Calculates the approximate numerical derivative of a function, at a point.

Command Syntax

nDeriv(f(variable),variable,value[,h])

Menu Location

Press:

  1. MATH to access the math menu.
  2. 8 to select nDeriv(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

nDeriv(f(var),var,value[,h]) computes an approximation to the value of the derivative of f(var) with respect to var at var=value. h is the step size used in the approximation of the derivative. The default value of h is 0.001.

nDeriv( only works for real numbers and expressions. nDeriv( can be used only once inside another instance of nDeriv(.

π→X
     3.141592654
nDeriv(sin(T),T,X)
     -.9999998333
nDeriv(sin(T),T,X,(abs(X)+e-6)e-6)
     -1.000000015
nDeriv(nDeriv(cos(U),U,T),T,X)
     .999999665

Advanced

If the default setting for h doesn't produce a good enough result, it can be difficult to choose a correct substitute. Although larger values of h naturally produce a larger margin of error, it's not always helpful to make h very small. If the difference between f(x+h) and f(x-h) is much smaller than the actual values of f(x+h) or f(x-h), then it will only be recorded in the last few significant digits, and therefore be imprecise.

A suitable compromise is to choose a tolerance h that's based on X. As suggested here, (abs(X)+E-6)E-6 is a reasonably good value that often gives better results than the default.

Formulas

The exact formula that the calculator uses to evaluate this function is:

(1)
\begin{align} \operatorname{nDeriv}(f(t),t,x,h)=\frac{f(x+h)-f(x-h)}{2h} \end{align}

(.001 is substituted for h when the argument is omitted)

Error Conditions

  • ERR:DOMAIN is thrown if h is 0 (since this would yield division by 0 in the formula)
  • ERR:ILLEGAL NEST is thrown if nDeriv( commands are nested more than one level deep. Just having one nDeriv( command inside another is okay, though.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/nderiv


The newList() Command

newlist.png

Command Summary

Returns a list filled with zeroes.

Command Syntax

newList(length)

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The newList() command returns a list of a specific length that is filled entirely with zeroes.

:newList(3)
           {0  0  0}
:newList(5)
           {0  0  0  0  0}
:newList(0)
           {}

This can be easily expanded to returning a list filled with any value: to return a list filled with a value x, just add x to the result of newList(). This works for strings as well, since "Hello"+0 simplifies to "Hello".

Advanced Uses

newList() can be used for making a comparison between a single value and a list. Normally, something like {1,2,3,4}=2 simply returns "false", since 2 is not a list and {1,2,3,4} is. To do a comparison element-by-element, use newList() to turn the single value into a list: in this case, 2+newList(4). Comparing {1,2,3,4} to 2+newList(4) will return {false, true, false, false} (you might use when() to get a single value out of this list).

This works to extend other operations to a number and a list, as well, though comparisons are the most useful application of this technique, since most operations already work this way.

Optimization

In many cases, an expression with newList() can be used to optimize a seq() command. First, observe that the simple

:seq(k,k,1,n)

which will return the list {1,2,3,…,n}, can be replaced by
:cumSum(1+newList(n))

The result is about twice as fast.

This is useful because many seq() expressions can be expressed using something like seq(k,k,1,n). For example:

:seq(k^2,k,1,n)

can be

:seq(k,k,1,n)^2

which is

:cumSum(1+newList(n))^2

This rearrangement is not always possible, but when it is, it gives a significant improvement in speed, with no real difference in size.

Here is a more complicated example (which is a sequence of probabilities with the binomial distribution). Notice the use of the with operator.

:seq(nCr(n,k) p^k (1-p)^(n-k),k,1,n)

can be

:nCr(n,a) p^a (1-p)^(n-a)|a=cumSum(1+newList(n))

Error Conditions

260 - Domain error happens when the length is not an integer ≥0.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:newlist


The NewPic command

newpic.png

Command Summary

Forms a new picture out of a n x 2 matrix.

Command Syntax

NewPic matrix, picVar[, maxRow][, maxColumn]

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

This command forms a new picture from a matrix. The matrix must have only 2 columns, and should contain as many rows as there are "on" pixels (darkened pixels) in the image. If the picture variable specified already exists, this command will overwrite it. This command takes each row of the matrix, and forms pixel coordinates from the two numbers there. The optional arguments maxRow and maxColumn specify the boundaries of the picture, so this is a good way to form a small sprite from a matrix.

:newPic [1,1;2,2;3,3;4,4;5,5], picline

The above code would form a picture named "picline" which would have pixels at (1,1),(2,2),(3,3),(4,4), and (5,5), which would basically be a straight line.

Error Conditions

260 - Domain error happens when an element of the matrix is outside the screen range..

230 - Dimension error happens when The matrix has more or less then 2 columns..

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:newpic


The ►Nom( Command
NOM.GIF

Command Summary

Converts an effective interest rate to a nominal interest rate.

Command Syntax

►Nom(interest rate,compounding periods)

Menu Location

On the TI-83, press:

  1. 2nd FINANCE to access the finance menu.
  2. ALPHA B to select ►Nom(.

On the TI-83+ or higher, press:

  1. APPS to access the applications menu.
  2. ENTER or 1 to select Finance…
  3. ALPHA B to select ►Nom(.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The ►Nom( command converts from an effective interest rate to a nominal interest rate. In other words, it converts an interest rate that takes compounding periods into account into one that doesn't. The two arguments are 1) the interest rate and 2) the number of compounding periods.

For example, you want to know the interest rate, compounded monthly, that will yield a total increase of 10% per year:

►Nom(10,12)
    9.568968515

Formulas

The formula for converting from an effective rate to a nominal rate is:

(1)
\begin{align} \operatorname{Nom}=100 \operatorname{CP} \left(\sqrt[\operatorname{CP}]{\frac{\operatorname{Eff}}{100}+1}-1\right) \end{align}

Here, Eff is the effective rate, Nom is the nominal rate, and CP is the number of compounding periods.

Error Conditions

  • ERR:DOMAIN is thrown if the number of compounding periods is not positive, or if the nominal rate is -100% or lower (an exception's made for the nominal rate if there is only one compounding period, since ►Nom(X,1)=X).

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/nom


The Normal Command
NORMAL.GIF

Command Summary

Puts the calculator in "normal" mode regarding scientific notation.

Command Syntax

Normal

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. ENTER to select Normal.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Normal command puts the calculator in normal number mode, in which it only uses scientific notation for large enough numbers (10 000 000 000 or higher), negative numbers large enough in absolute value (-10 000 000 000 or lower), or numbers close enough to 0 (less than .001 and greater than -.001)

The other possible settings are Sci (which always uses scientific notation), or Eng (which uses a specific form of scientific notation based on powers of 1000)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/normal


The normalcdf( Command
NORMALCDF.GIF

Command Summary

Finds the probability for an interval of the normal curve.

Command Syntax

normalcdf(lower, upper [, μ, σ])

Menu Location

Press:

  1. 2ND DISTR to access the distribution menu
  2. 2 to select normalcdf(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

normalcdf( is the normal (Gaussian) cumulative density function. If some random variable follows a normal distribution, you can use this command to find the probability that this variable will fall in the interval you supply.

There are two ways to use normalcdf(. With two arguments (lower bound and upper bound), the calculator will assume you mean the standard normal distribution, and use that to find the probability corresponding to the interval between "lower bound" and "upper bound". You can also supply two additional arguments to use the normal distribution with a specified mean and standard deviation. For example:

for the standard normal distribution
:normalcdf(-1,1

for the normal distribution with mean 10 and std. dev. 2.5
:normalcdf(5,15,10,2.5

Advanced

Often, you want to find a "tail probability" - a special case for which the interval has no lower or no upper bound. For example, "what is the probability x is greater than 2?". The TI-83+ has no special symbol for infinity, but you can use E99 to get a very large number that will work equally well in this case (E is the decimal exponent obtained by pressing [2nd] [EE]). Use E99 for positive infinity, and -E99 for negative infinity.

The normal distribution is often used to approximate the binomial distribution when there are a lot of trials. This isn't really necessary on the TI-83+ because the binompdf( and binomcdf( commands are already very fast - however, the normal distribution can be slightly faster, and the skill can come in handy if you don't have access to a calculator but do have a table of normal distributions (yeah, right). Here is how to convert a binomial distribution to a normal one:

:binompdf(N,P,X
can be
:normalcdf(X-.5,X+.5,NP,√(NP(1-P

:binomcdf(N,P,X,Y
can be
:normalcdf(X-.5,Y+.5,NP,√(NP(1-P

How much faster this is will depend on N and P, since the binomial distribution takes a long time to evaluate for large values of N, but the normal distribution takes about the same time for any mean and standard deviation. Also, this is an approximation that is only valid for some binomial distributions - a common rule of thumb is NP>10.

Formulas

As with other continuous distributions, any probability is an integral of the probability density function. Here, too, we can define normalcdf( for the standard normal case in terms of normalpdf(:

(1)
\begin{align} \operatorname{normalcdf}(a,b)=\int_a^b \operatorname{normalpdf}(x) \, \mathrm{d}x=\frac1{\sqrt{2\pi\,}} \int_a^b e^{-\frac1{2}x^2} \, \mathrm{d}x \end{align}

or in terms of the error function:

(2)
\begin{align} \operatorname{normalcdf}(a,b)=\frac1{2}\left(\operatorname{erf}\left(\frac{b}{\sqrt{2}}\right)-\operatorname{erf}\left(\frac{a}{\sqrt{2}}\right)\right) \end{align}

For the arbitrary mean μ and standard deviation σ, normalcdf( is defined in terms of the standard normal distribution, with the bounds of the interval standardized:

(3)
\begin{align} \operatorname{normalcdf}(a,b,\mu,\sigma)=\operatorname{normalcdf}\left(\frac{a-\mu}{\sigma},\frac{b-\mu}{\sigma} \right) \end{align}

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/normalcdf


The normalpdf( Command
NORMALPDF.GIF

Command Summary

Evaluates the normal probability density function at a point.

Command Syntax

normalpdf(x[,μ, σ])

Menu Location

Press:

  1. 2ND DISTR to access the distribution menu
  2. ENTER to select normalpdf(.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

normalpdf( is the normal (Gaussian) probability density function.

Since the normal distribution is continuous, the value of normalpdf( doesn't represent an actual probability - in fact, one of the only uses for this command is to draw a graph of the normal curve. You could also use it for various calculus purposes, such as finding inflection points.

The command can be used in two ways: normalpdf(x) will evaluate the standard normal p.d.f. (with mean at 0 and a standard deviation of 1) at x, and normalpdf(x,μ,σ) will work for an arbitrary normal curve, with mean μ and standard deviation σ.

Formulas

For the standard normal distribution, normalpdf(x) is defined as

(1)
\begin{align} \operatorname{normalpdf}(x)=\frac1{\sqrt{2\pi\,}} \, e^{-\frac1{2}x^2} \end{align}

For other normal distributions, normalpdf( is defined in terms of the standard distribution:

(2)
\begin{align} \operatorname{normalpdf}(x,\mu,\sigma)=\frac{1}{\sigma} \, \operatorname{normalpdf} \left(\frac{x-\mu}{\sigma}\right) \end{align}

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/normalpdf


The not (~) Command

not.png

Command Summary

Reverses a condition.
Can also be used as a bitwise "not" on integers.

Command Syntax

not condition
not integer

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 8 to enter the Test submenu.
  • Press 7 to select not.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The "not" operator reverses a condition, making it true if it had been false, and false if it had been true. You can create these conditions with the relational operators =, , >, , <, and , with functions such as isPrime(), pxlTest(), and ptTest(), or with any other expression that returns 'true' or 'false'. Other operators for dealing with conditions are and, or, and xor.

In output, it can also appear as ~, and if you type the ~ character, it will be interpreted as "not".

:not 2+2=4
           false
:not x
           ~x

The operator can also be applied to an integer, treating it as a 32-bit signed integer (larger integers will be truncated to fit) expressed in binary. In this case, it gives the 1's complement, flipping all the bits.

:(not 0b1111)▶Bin
           0b11111111111111111111111111110000
:not 1000
           -1001

Error Conditions

60 - Argument must be a Boolean expression or integer happens when the data type is incorrect.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:not


The not( Command
NOT.GIF

Command Summary

Flips the truth value of its argument.

Command Syntax

not(value)

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. RIGHT to access the LOGIC submenu.
  3. 4 to select not(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The last logical operator available on the 83 series takes only one value as input. not( comes with its own parentheses to make up for this loss. Quite simply, it negates the input: False becomes True (1) and True returns False (0). not( can be nested; one use is to make any True value into a 1.

:not(0)
           1

:not(-20 and 14)

           0

:not(not(2))
           1

Advanced Uses

not(not(X)) will make any value X into 1 if it's not 0, and will keep it 0 if it is.

Optimization

not(X) and X=0 have the same truth value, but not( is shorter if the closing parenthesis is omitted:

:If A=0
can be
:If not(A

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/not


The nPr Command
NPR.GIF

Command Summary

Calculates the combinatorial number of permutations.

Command Syntax

a nPr b

Menu Location

Press:

  1. MATH to access the math menu.
  2. LEFT to access the PRB submenu.
  3. 2 to select nPr, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

nPr is the number of permutations function, defined as a nPr b = a!/(a-b)!, where a and b are nonnegative integers. The function also works on lists.

Tip: nPr has a higher priority in evaluation than operators such as + or *: for example, 5X nPr 10 will be interpreted as 5(X nPr 10) and not as (5X) nPr 10. You might wish to use parentheses around complex expressions that you will give to nPr as arguments.

6 nPr 4
     360

The combinatorial interpretation of a nPr b is the number of ways to choose b objects in order, when there are a objects in total. For example, when giving 1st, 2nd, and 3rd place awards in a competition between 10 teams, there are 10 nPr 3 different ways to assign the awards.

Error Conditions

  • ERR:DIM MISMATCH is thrown when applying nPr to two lists that have different dimensions.
  • ERR:DOMAIN is thrown for negative integers or decimals.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/npr


The npv( Command
NPV.GIF

Command Summary

Computes the net present value of money over a specified time period.

Command Syntax

npv(interest rate,CF0,CFList[,CFFreq])

Menu Location

Press:

  1. 2nd FINANCE (on a TI-83) or APPS (TI-83+ or higher) to access the finance menu
  2. On the TI-83+ or higher, select the first option "Finance…" from the APPS menu
  3. 7 or use arrow keys to scroll to it

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The npv( command computes the net present value of money over a specified time period. If a positive value is returned after executing npv(, that means it was a positive cashflow; otherwise it was a negative cashflow. The npv( command takes four arguments, and the fourth one is optional:

  • interest rate — the percentage of the money that is paid for the use of that money over each individual period of time.
  • CF0 — the initial amount of money that you start out with; this number must be a real number, otherwise you will get a ERR:DATA TYPE error.
  • CFList — the list of cash flows added or subtracted after the initial money.
  • CFFreq — the list of frequencies of each cash flow added after the initial money; if this is left off, each cash flow in the cash flow list will just appear once by default.

Sample Problem

Your mom recently opened a bank account for you, with $500 as a gift to start you off. This is welcome news to you, until you find out that the bank charges 5% as the interest rate for the account. So, you get a job at Rocco's Pizzas delivering pizzas, which brings in $1,000-$2,000 each month. For the last five months, in particular, you have earned $1,250, $1,333, $1,575, $1,100, and $1,900. (Assume there are no other expenses, such as gas, car payment, etc.)

Plugging in all of the different values into the npv( command, this is what our code looks like:

:npv(5,500,{1250,1333,1575,1100,1900

Optimization

The npv( command's optional fourth argument should be left off if each cash flow of money in the list of cash flows just appears once.

:npv(5,1550,{2E3,3E3,4E3},{1,1,1
can be
:npv(5,1550,{2E3,3E3,4E3

At the same time, if there are cash flows that occur multiple times, it can be smaller to just use the frequency argument:

:npv(8,0,{200,200,300,300,300
can be
:npv(8,0,{200,300},{2,3

Formulas

Without a frequency list, the formula for npv( is the following:

(1)
\begin{align} \definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} \operatorname{npv}(i,\operatorname{CF}_0,\{\operatorname{CF}_j\})=\sum_{j=0}^N{\operatorname{CF}_j\left(1+\frac{i}{100}\right)^{-j}} \end{align}

When a frequency list is used, the same formula can be applied if we expand the list with frequencies into a long list without frequencies. However, it's possible to do the calculation directly. We define the cumulative frequency Sj as the sum of the first j frequencies (S0 is taken to be 0):

(2)
\begin{align} \definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} \operatorname{npv}(i,\operatorname{CF}_0,\{\operatorname{CF}_j\},\{n_j\}) =\operatorname{CF}_0+\sum_{j=1}^N{\operatorname{CF}_j\left(1+\frac{i}{100}\right)^{S_{j-1}}\frac{(1-(1+\frac{i}{100})^{-n_j})}{i}} \end{align}

Error Conditions

  • ERR:DATA TYPE is thrown if you try to use anything other than a real number for the interest rate.
  • ERR:DIM MISMATCH is thrown if the list of cash flows and the list of cash flow frequencies have different dimensions.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/npv


The OneVar Command

onevar.png

Command Summary

Calculates several summary statistics for a list.

Command Syntax

OneVar list[,freq,arg3,arg4]

Menu Location

  1. Press 2nd MATH to enter the MATH popup menu.
  2. Press 6 to enter the Statistics submenu.
  3. Press 1 to select OneVar.

Calculator Compatibility

This command works on all calculators.

Token Size

3 bytes

The OneVar command generates some summary statistics for a list. In its simplest form, it takes one argument — a list variable to analyze (it won't work with a list expression). It will store results to the following system variables:

  • $\bar{x}$ — the average, as given by mean()
  • Σx — the sum, as given by sum()
  • Σx2 — the sum of squares
  • Sx — the sample standard deviation, as given by stdDev()
  • σx — the population standard deviation, as given by stDevPop()
  • nStat — the length of the list, as given by dim()
  • minX — the smallest element, as given by min()
  • q1 — the first quartile
  • medStat — the median, as given by median()
  • q3 — the third quartile
  • maxX — the largest element, as given by max()

It won't actually display any of these results without prompting (although you could check the variables to find out their values). To display all of these statistics, use the ShowStat command.

Advanced Uses

The OneVar command takes up to 4 list arguments. The second argument, if present, is a list of frequencies. This must be the same length as the first list, and if it's there, its Nth element indicates how many times the Nth element of the first list should be counted. The calculator has no problems accepting zero or fractional numbers as frequencies.

The third and fourth arguments don't actually have an application. Their intention is to divide the elements into several categories: the third list would indicate which category each element of the data list falls under, and the fourth list would be a list of categories. However, this was apparently never implemented, and adding these lists doesn't affect the output.

Error Conditions

230 - Dimension happens when either the data list is {}, or the frequency list only contains 0s.

240 - Dimension mismatch happens when the frequency list (or the category list) isn't the same length as the data list.

260 - Domain happens when the frequency list contains negative elements.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:onevar


The OpenLib( Command
OPENLIB.png

Command Summary

Sets up a compatible Flash application library for use with ExecLib

Command Syntax

OpenLib(library)

Menu Location

This command is only found in the catalog menu. Press:

  1. 2nd CATALOG to access the command catalog.
  2. O to skip to commands starting with O.
  3. ENTER to select OpenLib(.

Calculator Compatibility

TI-84+/SE

Token Size

2 bytes

Together with ExecLib, OpenLib( is used on the TI-84 Plus and TI-84 Plus SE for running routines from a Flash App library. This only works, of course, with libraries that have been specifically written for this purpose. The only such library so far is usb8x, for advanced interfacing with the USB port.

The following program, which displays the version of usb8x, is an example of how to use OpenLib( and ExecLib:

:OpenLib(USBDRV8X
:{6
:ExecLib
:Ans(2)+.01Ans(3

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/openlib


The or Command
OR.GIF

Command Summary

Returns the truth value of value1 or value2 being true.

Command Syntax

value1 or value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. RIGHT to access the LOGIC submenu.
  3. 2 to select or, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

or takes two numbers or expressions, and checks to see if either one is True. If both are False, it returns 0. If at least one is True, it returns 1. or is commutative (i.e. the order of arguments does not matter). As with and, you can use variables and expressions, and use multiple or's together.

:0 or 1-1
           0

:0 or -1
           1

:2 or 6*4
           1

:0 or 1 or 0
           1

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/or


The or Command

or.png

Command Summary

Tests if either of two conditions is true.
Can also be used as a bitwise "or" on integers.

Command Syntax

condition1 or condition2
integer1 or integer2

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 8 to enter the Test submenu.
  • Press 9 to select or.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The "or" operator combines two conditions into one, which will be true if either side is true, and false if both are false. You can create these conditions with the relational operators =, , >, , <, and , with functions such as isPrime(), pxlTest(), and ptTest(), or with any other expression that returns 'true' or 'false'. Other operators for dealing with conditions are and, xor, and not.

:2+2=4 or 1=0
           true
:2+2=5 or 1+1=3
           false

The operator can also be applied to integers, treating them as 32-bit signed integers (larger integers will be truncated to fit) expressed in binary. The bits will be matched up, and "or" will be applied to the bits individually — a bit in the result will be 1 if either of the two corresponding bits of the original integers was 1, and 0 otherwise.

:(0b11111100 or 0b00111111)▶Bin
           0b11111111
:256 or 512
           768

In complicated logical expressions (both with conditions and with integers), "and" has greater priority than the others ("or" and "xor"). For instance, X or Y and Z will be interpreted as X or (Y and Z).

Error Conditions

60 - Argument must be a Boolean expression or integer happens when the data type is incorrect (or mismatched).

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:or


The ord() Command

ord.png

Command Summary

Gives the ASCII code of a character.

Command Syntax

ord(string)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press D to enter the string submenu.
  • Press B to select ord(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The ord() command gives the ASCII code of a character (that is, its character code, which is a modification of standard ASCII). The input is meant to be a single character, but the command doesn't actually check for that — so in practice, it gives the ASCII code of the first character in a string. You can convert multiple characters at once by giving ord() a list (or matrix) of characters.

The inverse of ord() is char(), which converts a character code to a character.

:ord("America")
           65
:ord({"A","b","c"})
           {65  98  99}
:ord("")
           0

Optimization

Code such as

:inString("ABCDEFGHIJKLMNOPQRSTUVWXYZ",str)

should be replaced by appropriate use of ord(); in this case,
:ord(str)-64

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:ord


The Output Command

output.png

Command Summary

Output is used to display text to pixel coordinates on the Program I/O screen.

Command Syntax

Output row,col,text

Menu Location

Starting in the program editor:

  • Press F3 to enter the I/O menu.
  • Press 6 to paste Output.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The Output command is the most basic command for displaying text. It can display any type of expression on the Program I/O screen in the large font, using "Pretty Print" if it is enabled. It uses (row, column) pixel coordinates to determine the top left corner from which it displays the expression. By far the most common use of Output is for displaying strings.

:Output 20,20,"Hello, world"

Advanced Uses

Both the row and the column coordinates for displaying text can be arbitrary integers — they can be negative, and they can go off-screen. The portion of the text that fits on the screen (if any) is drawn, and the rest is omitted: there is no wrapping of any kind.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:output


The Output( Command
OUTPUT_ANIMATED.gif

Command Summary

Displays an expression on the home screen starting at a specified row and column. Wraps around if necessary.

Command Syntax

Output(row, column, expression)

Menu Location

While editing a program press:

  1. PRGM to enter the PRGM menu
  2. RIGHT to enter the I/O menu
  3. 6 to choose Output(, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Output( command is the fastest way to display text on the home screen. It takes three arguments: the row (1-8) at which you want to display something, the column (1-16), and whatever it is you want to display. It allows for more freedom than the Disp command.

Although off-screen values for the row and column values will cause an error, it's okay if part of the text displayed goes off the screen. When text goes past the last (16th on monochrome calculators, 26th on color calculators) column, it will wrap to the first column of the next row. If the text goes past the last column of the last row, the remainder will be truncated. Output( will never cause the screen to scroll.

When the horizontal screen split mode is activated, only the first four rows of the home screen are available for the Output( command, which may cause undesirable behavior, and trying to output to the last four rows will cause an error. It is advisable to use the Full command at the beginning of a program that relies on Output(.

Like other text display commands, you can display each function and command as text. However, this is not without problems as each function and command is counted as one character. The two characters that you can't display are quotation marks (") and the store command (→). However, you can mimic these respectively by using two apostrophes (' ' ), and two subtract signs and a greater than sign (—>).

Advanced Uses

If the last text display command of a program is an Output( command, then "Done" will not be displayed as the program finishes. Some programmers use this to get rid of the Done message by using an empty Output( command at the end (there is no text after the quote):

:Output(1,1,"

This trick does not work on recent "MathPrint" OSes.

You can also use Output( to get rid of the run indicator. Unfortunately, it only silences it for a moment and needs to be repeated in a loop to make it appear to be gone. In a game, it should be incorporated into the main loop. The run indicator is momentarily stopped every time that you output something to the upper right corner, it just needs to be repeated for it to appear to be gone. If you're on the graph screen, you can accomplish the same thing using the Text( command.

:Output(1,16," "

Since the text displayed by an Output( command wraps, a single command can be used to overwrite the entire screen by displaying 8*16=128 (10*26=260 for color calculators) characters of text starting from row 1, column 1. Since every space on the screen is overwritten, this does not require a ClrHome to clear previously displayed characters. Keep in mind that exactly 16 (26 on color calculators) characters will be on each line.

Optimization

Output( does not allow for more than one expression to be displayed by a single command. However, if several strings are going to be displayed next to each other by several commands they might be combined into one (keep in mind how wrapping works):

:Output(3,3,"Some Text Here
:Output(4,3,"More Text Here
can be
:Output(3,3,"Some Text Here    More Text Here

In addition, if you are displaying text on the entire home screen, you can place the all the text in a string and then simply display the string. This is especially useful when combined with movement because you can shift the screen quite easily.

:Output(1,1,Str1

Command Timings

The Output( command is the fastest possible way of displaying text (short of storing text to a picture and then recalling it). In particular, when going for speed, it should be preferred instead of Disp.

Error Conditions

  • ERR:DOMAIN is thrown when the starting row or column are not integers in the valid range (this is affected by split screen mode).
  • ERR:INVALID occurs if this statement is used outside a program.
  • An error is not thrown when the argument is an empty list (unlike with Disp or pretty much anything else, really)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/output


The Param Command
PARAM.GIF

Command Summary

Enables parametric graphing mode.

Command Syntax

Param

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. Use arrows to select Par.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Param command enables parametric graphing mode.

Parametric mode is in many ways a generalization of function mode. Instead of writing y as a function of x, both x and y are written as a function of a parameter t (hence the name, parametric mode). You can easily see that equations in function mode are just a special case of equations in parametric mode: if you set x equal to t, then writing y=f(t) is equivalent to writing y=f(x). Of course, graphing a function this way on a calculator will be slightly slower than doing it in function mode directly, because of the overhead.

Parametric mode allows you the greatest freedom of all the possible graphing modes - nearly every curve you could encounter can be expressed in parametric form.

In mathematics, the parameter t is commonly allowed to take on all values from negative to positive infinity. However, this would be impossible to do on a calculator, since the equation would never stop graphing (unlike function mode, there's no easy way to check for which values of t the equation will go off the screen and there's no need to graph it). Instead, the calculator has window variables Tmin, Tmax, and Tstep: it will evaluate the parameter at every value from Tmin to Tmax, increasing by Tstep each time, and 'connect the dots'.

Polar mode, which you'll read about in the next section, is also a special case of parametric mode: To graph r=f(θ), you can instead graph x=f(t)cos(t) and y=f(t)sin(t), with t graphed over the same interval as θ.

Advanced Uses

The window variables that apply to parametric mode are:

  • Tmin — Determines the minimum T-value graphed for equations.
  • Tmax — Determines the maximum T-value graphed for equations.
  • Tstep — Determines the difference between consecutive T-values.
  • Xmin — Determines the minimum X-value shown on the screen.
  • Xmax — Determines the maximum X-value shown on the screen.
  • Xscl — Determines the horizontal space between marks on the X-axis in AxesOn mode or dots in GridOn mode.
  • Ymin — Determines the minimum Y-value shown on the screen.
  • Ymax — Determines the maximum Y-value shown on the screen.
  • Yscl — Determines the vertical space between marks on the Y-axis in AxesOn mode or dots in GridOn mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/param


The Pause Command
PAUSE_ANIMATED.gif

Command Summary

Pauses the program until the user presses ENTER.

Command Syntax

Pause [value-or-text]

Menu Location

While editing a program, press:

  1. PRGM to enter the PRGM menu
  2. 8 to choose Pause, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Pause command is used for suspending the execution of a program at a certain point. This is useful when you have text or instructions on the home screen that you want the user to read before the program continues on to the next thing. While the program is paused, the pause indicator turns on in the top-right corner of the screen (it is the dotted line that moves around).

After the user is done reading the text or instructions, they must press ENTER to resume program execution. One place the Pause command is commonly used is right before clearing the screen with ClrHome, because otherwise the text on the screen will show up for a split second before it is erased. The Pause command gives the user ample time to look at and read the text.

:Pause

An alternative to the Pause command that is commonly used is a Repeat loop with a getKey command as the condition. This is sometimes more appropriate in a program if you don't want to bring the program to a complete standstill, and you want the user to be able to resume program execution with any key instead of just ENTER (see usability for more information).

:Repeat getKey
:End

Advanced Uses

The Pause command has an optional argument that can either be text, a number, a variable, or an expression. This argument will be displayed on the next available blank line on the home screen while the program is paused, and it can be scrolled if it is larger than the screen. Although the Pause command can be used with the graph screen, the argument will still be displayed on the home screen.

Caution: Unlike any other text command, or indeed any other command at all, this optional argument will be stored to Ans after the pause! This could be used to your advantage, but most of the time, it's a nuisance, and if you use Ans for optimization, watch out for this side effect.

Displaying text with the Pause command follows the same pattern as the Disp command, so text is displayed on the left and everything else is displayed on the right. It also means that if there is already text on the seventh row, it will automatically move everything up one row so it can display its text. In addition, the Pause command is affected by the Output( command and its text.

PROGRAM:PAUSE
:ClrHome
:"World!
:Disp " Hello "+Ans
:Output(2,2,"Goodbye
:Pause Ans

When the calculator is paused, it is possible for another linked calculator to use the GetCalc( command to transfer a variable.

The TI-84+CE also introduced an optional second argument to the Pause command. With this argument, you can specify the amount of time you wish to wait for in seconds:

:Pause "HELLO",2

Using the empty string "" with the optional second argument will cause the Pause command to wait for the specified amount of time without displaying anything on the screen:
:Pause "",3.5

The more recent Wait command can do this as well. Here’s the first example, but using Wait:
:Disp “HELLO
:Wait 2

Optimization

When you have a Disp command before a Pause command, you can take the text or variable from the Disp command and place it after the Pause command as its optional argument. This allows you to remove the Disp command. If the Disp command has multiple arguments, you just take the last one off and put it as the optional argument.

:Disp A
:Pause
can be
:Pause A

When using the optional argument of Pause, it is stored to Ans, and this can in rare cases be used for optimization. The most common one would probably be using Pause to show work for a calculation, as in the following program:

:Disp "A+B=
:Pause A+B
:Disp "(A+B)²=
:Pause Ans²
:Disp "(A+B)²-C²=
:Pause Ans-C²

Error Conditions

  • ERR:INVALID occurs if this statement is used outside a program.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pause


The Pause Command

pause.png

Command Summary

Pauses the program until ENTER is pressed, optionally displaying text on the I/O screen.

Command Syntax

:Pause [expression]

Menu Location

Starting in the program editor:

  • Press F2 to enter the Control menu.
  • Press 8 to enter the Transfers submenu.
  • Press 1 to select Pause.

Calculator Compatibility

This command works on all calculators.

Token Size

3 bytes

Used by itself without parameters, Pause temporarily suspends the program until the ENTER key is pressed, displaying an indicator to that effect in the lower right corner of the screen. When ENTER is pressed, the program continues running from the next command in order.

Pause can also be given any expression as a parameter. In this case, it will display the expression on a new line on the Program I/O screen (just like Disp), and then pause the program as above. Unlike Disp, however, it can only display one thing.

Optimization

Make sure to give Pause an argument if using it with Disp:

:Disp x
:Pause

can be

:Pause x

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:pause


The Pen Tool
PEN.GIF

Command Summary

Allows the user to draw on the graph screen.

Command Syntax

Pen isn't a command, it's a menu option.

Menu Location

From the home screen, press:

  1. 2nd PRGM to enter the DRAW menu
  2. Scroll up to select Pen, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

The Pen tool allows you to draw on the graph screen using a + cursor for the "pen", similar to what you see when accessing the graph screen with graphs or with the Input command. You can find Pen by pressing [2nd][PRGM] to go to the DRAW menu, but it is only accessible from the calculator's home screen (where you do math and run programs); it won't show up when you are inside the program editor.

You use the arrow keys to move the pen around, and you can press [2nd][<] and [2nd][>] to move five pixels over instead of just the typical one (this does not work with the up or down keys, since that would change the calculator's contrast). Pressing ENTER starts or stops the drawing respectively, and you just have to press CLEAR twice to return back to the home screen.

When you are done drawing, the calculator stores the coordinates of the cursor to the respective graph screen variables (R and θ for PolarGC format, otherwise X and Y).

Unfortunately, anything that you draw with Pen will be erased or overwritten whenever another program accesses the graph screen or somebody graphs something, so you should store it to a picture if you want to keep it for future use.

Even more unfortunately, you can't erase pixels with Pen. If you're the type of person who makes mistakes once in a while, it might be better to go to the graph screen and choose Pt-Change( from the DRAW menu. This will require you to press ENTER for every pixel you want to draw, but it will also allow you to erase a pixel (by drawing to it again).

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pen


The Plot#( Commands
PLOTN.GIF

Command Summary

Displays a statistical plot of one of six types.

Command Syntax

Plot#(type,…

The syntax varies based on the type of plot:

Plot#(Scatter, x-list, y-list, mark)

Plot#(xyLine, x-list, y-list, mark)

Plot#(Histogram, x-list, freq list)

Plot#(Boxplot, x-list, freq list)

Plot#(ModBoxplot, x-list, freq list, mark)

Plot#(NormProbPlot, data list, data axis, mark)

Menu Location

While editing a program, press:

  1. 2nd PLOT to access the stat plot menu.
  2. 1, 2, or 3 (or use arrows) to select Plot1(, Plot2(, Plot3( respectively.

(outside a program, this brings you to the plot editor screen)

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The commands Plot1(, Plot2(, and Plot3(, which are identical except for which stat plot (1, 2, or 3) they affect, define their corresponding stat plot. When the stat plot is defined, it is also turned on so no PlotsOn command is necessary.

The first argument of the commands is always the type of plot, and is one of Scatter, xyLine, Histogram, Boxplot, ModBoxplot, and NormProbPlot - these types are found in the TYPE submenu of the stat plot menu. The other arguments vary. For all but Histogram and Boxplot, there is a mark argument - this is a dot, a cross, or a box, symbols that can be found in the MARK submenu of the stat plot menu.

Scatter plot

Plot#(Scatter, x-list, y-list, mark) defines a scatter plot. The points defined by x-list and y-list are plotted using mark on the graph screen.

x-list and y-list must be the same length.

xyLine plot

Plot#(xyLine, x-list, y-list, mark) defines an xyLine plot. Similarly to a scatter plot, the points defined by x-list and y-list are plotted using mark on the graph screen, but with an xyLine plot they are also connected by a line, in the order that they occur in the lists.

x-list and y-list must be the same length.

Histogram plot

Plot#(Histogram, x-list, freq list) defines a Histogram plot. The x-axis is divided into intervals that are Xscl wide. A bar is drawn in in each interval whose height corresponds to the number of points in the interval. Points that are not between Xmin and Xmax are not tallied.

Xscl must not be too small - it can divide the screen into no more than 47 different bars.

Box plot

Plot#(Boxplot, x-list, freq list) defines a box plot. A rectangular box is drawn whose left edge is Q1 (the first quartile) of the data, and whose right edge is Q3 (the third quartile). A vertical segment is drawn within the box at the median, and 'whiskers' are drawn from the box to the minimum and maximum data points.

The box plot ignores the Ymax and Ymin dimensions of the screen, and any plots that aren't box plots or modified box plots. Each box plot takes approximately 1/3 of the screen in height, and if more than one are plotted, they will take up different areas of the screen.

Modified box plot

Plot#(ModBoxplot, x-list, freq list, mark) defines a modified box plot. This is almost entirely like the normal box plot, except that it also draws outliers. Whiskers are only drawn to the furthers point within 1.5 times the interquartile range (Q3-Q1) of the box. Beyond this point, data points are drawn individually, using mark.

The box plot ignores the Ymax and Ymin dimensions of the screen, and any plots that aren't box plots or modified box plots. Each box plot takes approximately 1/3 of the screen in height, and if more than one are plotted, they will take up different areas of the screen.

Normal probability plot

Plot#(NormProbPlot, data list, data axis, mark) defines a normal probability plot. The mean and standard deviation of the data are calculated. Then for each point, the number of standard deviations it is from the mean is calculated, and the point is plotted against this number using mark. data axis can be either X or Y: it determines whether the value of a point determines it's x-coordinate or y-coordinate.

The point behind this rather convoluted process is to test the extent to which the data is normally distributed. If it follows the normal distribution closely, then the result will be close to a straight line - otherwise it will be curved.

Advanced Uses

After doing a regression, a scatter plot of ∟RESID against the x-list is a useful measure of the effectiveness of the regression. If the plot appears random, this is a good sign; if there is a pattern to the plot, this means it's likely that a better regression model exists.

Optimization

The ∟ symbol at the beginning of list names can be omitted everywhere in this command.

In addition, every element except the plot type and the data list or data lists are optional, and take on the following default values:

  • freq list is 1 by default, meaning that all frequencies are 1.
  • mark is the box by default.
  • data axis is X by default.

Error Conditions

  • ERR:DIM MISMATCH is thrown if the x and y lists, or the data and frequency lists, have different dimensions.
  • ERR:STAT is thrown if Xscl is too small in the case of a Histogram.

All errors are thrown when plotting the stat plot, as opposed to when the command is executed, and do not provide a 2:Goto option.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/plotn


The PlotsOff Command
PLOTSOFF.GIF

Command Summary

Turns stat plots (all of them, or only those specified) off.

Command Syntax

PlotsOff numbers//

Menu Location

Press:

  1. 2nd PLOT to access the stat plot menu.
  2. 4 to select PlotsOff, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

By itself, the command will turn off all three stat plots.

If it is given arguments, there can be any number of them (actually, no more than 255, but this won't stop most people), but they must all be numbers 1 to 3. Then, the command will only turn off the specified plots. Unlike some commands, it is okay to give PlotsOff an expression as an argument (for example, PlotsOff X), as long as it has a value of 1, 2, or 3.

Error Conditions

  • ERR:DOMAIN is thrown if a plot that is not 1, 2, or 3 is specified.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/plotsoff


The PlotsOn Command
PLOTSON.GIF

Command Summary

Turns stat plots (all of them, or only those specified) on.

Command Syntax

PlotsOn numbers//

Menu Location

Press:

  1. 2nd PLOT to access the stat plot menu.
  2. 5 to select PlotsOn, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

By itself, the command will turn on all three stat plots.

If it is given arguments, there can be any number of them (actually, no more than 255, but this won't stop most people), but they must all be numbers 1 to 3. Then, the command will only turn on the specified plots. Unlike some commands, it is okay to give PlotsOn an expression as an argument (for example, PlotsOn X), as long as it has a value of 1, 2, or 3.

Error Conditions

  • ERR:DOMAIN is thrown if a plot that is not 1, 2, or 3 is specified.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/plotson


The Pmt_Bgn Command
PMT_BGN.GIF

Command Summary

Sets the TVM solver to use payments at the beginning of a period.

Command Syntax

Pmt_Bgn

Menu Location

On the TI-83, press:

  1. 2nd FINANCE to access the finance menu.
  2. ALPHA F to select Pmt_Bgn, or use arrows and ENTER.

On the TI-83+ or higher, press:

  1. APPS to access the applications menu.
  2. ENTER to select Finance…
  3. ALPHA F to select Pmt_Bgn, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The Pmt_Bgn and Pmt_End commands toggle a setting with the finance solver. In Pmt_Bgn mode, the calculator assumes that the payments are made at the beginning of each time period, rather than at the end.

Make sure to set the calculator to one of the modes before using the finance solving commands in a program, since otherwise the result is unpredictable.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pmt-bgn


The Pmt_End Command
PMT_END.GIF

Command Summary

Sets the TVM solver to use payments at the end of a period.

Command Syntax

Pmt_End

Menu Location

On the TI-83, press:

  1. 2nd FINANCE to access the finance menu.
  2. ALPHA E to select Pmt_End, or use arrows and ENTER.

On the TI-83+ or higher, press:

  1. APPS to access the applications menu.
  2. ENTER to select Finance…
  3. ALPHA E to select Pmt_End, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The Pmt_End and Pmt_Bgn commands toggle a setting with the finance solver. In Pmt_End mode, the calculator assumes that the payments are made at the end of each time period, rather than at the beginning.

Make sure to set the calculator to one of the modes before using the finance solving commands in a program, since otherwise the result is unpredictable.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pmt-end


The poissoncdf( Command
POISSONCDF.GIF

Command Summary

Calculates the Poisson cumulative probability for a single value

Command Syntax

poissoncdf(mean, value)

Menu Location

Press:

  1. 2ND DISTR to access the distribution menu
  2. ALPHA C to select poissoncdf(, or use arrows.

Press ALPHA D instead of ALPHA C on a TI-84+/SE with OS 2.30 or higher.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

This command is used to calculate Poisson distribution cumulative probability. In plainer language, it solves a specific type of often-encountered probability problem, that occurs under the following conditions:

  1. A specific event happens at a known average rate (X occurrences per time interval)
  2. Each occurrence is independent of the time since the last occurrence
  3. We're interested in the probability that the event occurs at most a specific number of times in a given time interval.

The poissoncdf( command takes two arguments: The mean is the average number of times the event will happen during the time interval we're interested in. The value is the number of times we're interested in the event happening (so the output is the probability that the event happens at most value times in the interval). Note that you may need to convert the mean so that the time intervals in both cases match up. This is done by a simple proportion: if the event happens 10 times per minute, it happens 20 times per two minutes.

For example, consider point on a city street where an average of 5 cars pass by each minute. What is the probability that in a given minute, no more than 3 cars will drive by?

  1. The event is a car passing by, which happens at an average rate of 5 occurences per time interval (a minute)
  2. Each occurrence is independent of the time since the last occurrence (we'll assume this is true, though traffic might imply a correlation here)
  3. We're interested in the probability that the event occurs at most 3 times in the time interval.

The syntax in this case is:

:poissoncdf(5,3

This will give about .265 when you run it, so there's a .265 probability that in a given minute, no more than 3 cars will drive by.

Formulas

The poissoncdf( command can be seen as a sum of poissonpdf( commands:

(1)
\begin{align} \definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} \operatorname{poissoncdf}(\lambda,k)=\sum_{i=0}^k \operatorname{poissonpdf}(\lambda,i) = \sum_{i=0}^k \frac {e^{-\lambda} \lambda^i}{i!} \end{align}

We can also write the poissoncdf( command in terms of the incomplete gamma function:

(2)
\begin{align} \definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} \operatorname{poissoncdf}(\lambda,k)=\frac{\Gamma(k+1,\lambda)}{k!} \end{align}

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/poissoncdf


The poissonpdf( Command
POISSONPDF.GIF

Command Summary

Calculates the Poisson probability for a single value

Command Syntax

poissonpdf(mean, value)

Menu Location

Press:

  1. 2ND DISTR to access the distribution menu
  2. ALPHA B to select poissonpdf(, or use arrows.

Press ALPHA C instead of ALPHA B on a TI-84+/SE with OS 2.30 or higher.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

This command is used to calculate Poisson distribution probability. In plainer language, it solves a specific type of often-encountered probability problem, that occurs under the following conditions:

  1. A specific event happens at a known average rate (X occurrences per time interval)
  2. Each occurrence is independent of the time since the last occurrence
  3. We're interested in the probability that the event occurs a specific number of times in a given time.

The poissonpdf( command takes two arguments: The mean is the average number of times the event will happen during the time interval we're interested in. The value is the number of times we're interested in the event happening (so the output is the probability that the event happens value times in the interval).

For example, consider point on a city street where an average of 5 cars pass by each minute. What is the probability that in a given minute, 8 cars will drive by?

  1. The event is a car passing by, which happens at an average rate of 5 occurrences per time interval (a minute)
  2. Each occurrence is independent of the time since the last occurrence (we'll assume this is true, though traffic might imply a correlation here)
  3. We're interested in the probability that the event occurs 8 times in the time interval

The syntax in this case is:

:poissonpdf(5,8

This will give about .065 when you run it, so there's a .065 probability that in a given minute, 8 cars will drive by.

Formulas

The value of poissonpdf( is given by the formula

(1)
\begin{align} \definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} \operatorname{poissonpdf}(\lambda,k) = \frac{e^{-\lambda}\lambda^k}{k!} \end{align}

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/poissonpdf


The Polar Command
POLAR-MODE.GIF

Command Summary

Enables polar graphing mode.

Command Syntax

Polar

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. Use arrows to select Pol.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Polar command enables the polar graphing mode.

Unlike the previous modes, polar mode doesn't use the more common (x,y) coordinates. Instead, the coordinates (r,θ) are used, where θ is the counterclockwise angle made with the positive x-axis, and r is the distance away from the origin (the point (0,0)). Although it's possible to translate from one system to the other, polar coordinates are more useful for some expressions (and, of course, less useful for others).

In particular, they're very good at graphing anything circle-related. The equation for a circle in polar mode is just r=1 (or any other number, for a circle of different radius).

Like in parametric mode, the parameter θ uses the window variables θmin, θmax, and θstep to determine which points are graphed. A common situation is θmin=0, θmax=2π: in Radian mode, this corresponds to going all the way around the circle. Of course, you could use Degree mode and set θmax to be 360, but this is uncommon in mathematics.

Advanced Uses

The window variables that apply to polar mode are:

  • θmin — Determines the minimum θ-value graphed for equations.
  • θmax — Determines the maximum θ-value graphed for equations.
  • θstep — Determines the difference between consecutive θ-values.
  • Xmin — Determines the minimum X-value shown on the screen.
  • Xmax — Determines the maximum X-value shown on the screen.
  • Xscl — Determines the horizontal space between marks on the X-axis in AxesOn mode or dots in GridOn mode.
  • Ymin — Determines the minimum Y-value shown on the screen.
  • Ymax — Determines the maximum Y-value shown on the screen.
  • Yscl — Determines the vertical space between marks on the Y-axis in AxesOn mode or dots in GridOn mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/polar-mode


The ►Polar Command
POLAR.GIF

Command Summary

Formats a complex value in polar form when displaying it.

Command Syntax

value►Polar

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT RIGHT to access the CPX submenu.
  3. 7 to select ►Polar, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The ►Polar command can be used when displaying a complex number on the home screen, or with the Disp and Pause commands. It will then format the number as though re^θi mode were enabled. It also works with lists.

i
    i
i►Polar
    1e^(1.570796327i)
{1,i}►Polar
    {1 1e^(1.570796327i)}

It will also work when displaying a number by putting it on the last line of a program by itself. It does not work with Output(, Text(, or any other more complicated display commands.

To actually separate a number into the components of polar form, use abs( and angle(.

Error Conditions

  • ERR:SYNTAX is thrown if the command is used somewhere other than the allowed display commands.
  • ERR:DATA TYPE is thrown if the value is real.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/polar-display


The PolarGC Command
POLARGC.GIF

Command Summary

Sets the calculator to display point coordinates using polar coordinates.

Command Syntax

PolarGC

Menu Location

Press:

  1. 2nd FORMAT to access the graph format screen
  2. Use arrows and ENTER to select PolarGC.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The PolarGC ("Polar Grid Coordinates") command (like its opposite, the RectGC) command, affects how the coordinates of a point on the graph screen are displayed. When PolarGC is enabled, the coordinates of a point are displayed as (R,θ).

The polar coordinates of a point can be interpreted as the distance R it is away from the origin (0,0), and the direction θ. θ is the angle that a ray to the point would make with the positive X-axis (so polar coordinates are affected by Degree/Radian mode). An angle of 0 means the point is to the left of the origin; an angle of 90° (π/2 radians) means it's up from the origin, and so on. So, for example, the point with R=2 and θ=270° (3π/2 radians) would be two units down from the origin.

Of course, coordinates are only displayed with the CoordOn setting; however, with CoordOff, RectGC and PolarGC are still useful, because in a variety of cases, the coordinates of a point are also stored to variables. PolarGC doesn't change the fact that they're stored to X and Y, as with RectGC; however, with PolarGC, they are also stored to R and θ.

Although the PolarGC command naturally goes with Polar graphing mode, the two settings are independent; you can use both PolarGC and RectGC with any graphing mode.

Advanced

The following situations involve storing coordinates of a point to variables:

  • Graphing an equation
  • Tracing an equation or plot
  • Moving the cursor on the graph screen
  • Using the interactive mode of one of the 2nd DRAW commands
  • Using one of DrawF, DrawInv, or Tangent(
  • Anything in the 2nd CALC menu.

Naturally, any command like Input or Select( which involves the above, will also store coordinates of a point.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/polargc


The prgm Command
PRGM.GIF

Command Summary

Calls another program from within a program, with program execution moving to that program.

Command Syntax

prgmNAME

Menu Location

Outside the editor, press:

  1. PRGM to enter the PRGM menu
  2. Use arrows to choose program

When editing a program, press:

  1. PRGM to enter the PRGM menu
  2. LEFT to enter the EXEC submenu
  3. select a program

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The prgm command is used to execute a program from inside another program (at any time while the program is running), with the secondary program acting as a subprogram for that program. Although they are listed in the program menu and can be executed independently like any other program, subprograms are primarily designed to do a particular task for the other program.

You insert the prgm command into the program where you want the subprogram to run, and then type (with the alpha-lock on) the program name. You can also go to the program menu to choose a program, pressing ENTER to paste the program name into your program.

PROGRAM:MYPROG
:ClrHome
:Output(3,3,"Hello
:prgmWHATEVER

When the subprogram name is encountered during a program, the program will be put on hold and program execution will transfer to the subprogram. Once the subprogram is finished, program execution will go back to the program, continuing right after the subprogram name.

Although subprograms can call themselves or other subprograms, this should be done sparingly because it can cause memory leaks if done too much or if the subprogram doesn't return to the parent program.

Branching is local to each program, so you can’t use Goto in one program to jump to a Lbl in another program. In addition, all variables are global, so changing a variable in one program affects the variable everywhere else.

Advanced Uses

Each time you call a TI-Basic program, 16 bytes are used to save your place in the original program so you can return to it correctly. This is a small enough amount that you don't have to worry about it, unless you're low on RAM or use a lot of recursion.

Error Conditions

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/prgm


The PrintScreen Command
PRINTSCREEN.GIF

Command Summary

This command doesn't exist. A token for it does, though.

Command Syntax

PrintScreen

Menu Location

This command requires a hex editor to access.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

This command is probably the vestigial remnant of a planned function that wasn't implemented. A token is set aside for it, but the command doesn't actually do anything, and will cause an error if you try to use it. It's not accessible through any menus, though, so that's okay.

The only potential use is to save on memory if you ever need to display "PrintScreen" somewhere - you can display this token instead.

Error Conditions

  • ERR:INVALID is thrown when trying to use this command.

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/printscreen


The prod( Command
PROD.GIF

Command Summary

Calculates the product of all or part of a list.

Command Syntax

prod(list[,start,[end]])

Menu Location

Press:

  1. 2nd LIST to access the list menu.
  2. LEFT to access the MATH submenu.
  3. 6 to select prod(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The prod( command calculates the product of all or part of a list.

When you use it with only one argument, the list, it multiplies all the elements of the list. You can also give it a bound of start and end and it will only multiply the elements starting and ending at those indices (inclusive).

prod({1,2,3,4,5})
    120
prod({1,2,3,4,5},2,4)
    24
prod({1,2,3,4,5},3)
    60

Optimization

If the value of end is the last element of the list, it can be omitted:

prod({1,2,3,4,5},3,5)
can be
prod({1,2,3,4,5},3)

Error Conditions

  • ERR:DOMAIN if the starting or ending value aren't positive integers.
  • ERR:INVALID DIM if the starting or ending value exceed the size of the list, or are in the wrong order.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/prod


The Prompt Command
PROMPT_ANIMATED.gif

Command Summary

Prompts the user to enter values for variables and then stores those values to the variables.

Command Syntax

Prompt variableA[,variableB,…]

Menu Location

While editing a program press:

  1. PRGM to enter the PRGM menu
  2. RIGHT to enter the I/O menu
  3. 2 to choose Prompt, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Prompt command is the simplest way of getting user input on the home screen (getting user input on the graph screen is only possible with the getKey command). Prompt displays variables one per line, with an equal sign and question mark (=?) displayed to the right of each variable. After the user enters a value or expression for the variables and presses ENTER, the values will be stored to the variables and program execution will resume.

Prompt can be used with every variable, but some of the variables have to be entered in a certain way. If the variable is a string or equation, the user must put quotes ("") around the value; the user must also put curly braces ({}) around lists and square brackets ([]) around matrices. Of course, ending quotes, braces, and brackets can be left off as usual.

When you use Prompt to input a named list, the in front of the name is dropped (so Prompt ∟NAME will display NAME=?). This can be confusing with single-letter names: Prompt ∟X and Prompt X both display X=?. Further enhancing the confusion, if the user enters a list for Prompt X, the list will be stored to ∟X instead.

During the Prompt, the user can press [2nd][MODE] to quit the program immediately.

Advanced Uses

Because simply displaying what variable the value will be stored to does not really tell the user what the variable will be used for, you can put a Disp command before Prompt to give the user some more insight into what an appropriate value for the variable would be. The Prompt command will be displayed one line lower, though, because the Disp command automatically creates a new line after itself. (Of course, you could also just use the Input command.)

:Disp "Enter the Score
:Prompt A

Optimizations

When you have a list of Prompt commands (and each one has its own variable), you can just use the first Prompt command and combine the rest of the other Prompt commands with it. You remove the Prompt commands and combine the arguments, separating each argument with a comma. The arguments can be composed of whatever combination of variables is desired.

The advantages of combining Prompt commands are that it makes scrolling through code faster, and it is more compact (i.e. smaller) and easier to write than using the individual Prompt commands. The primary disadvantage is that it is easier to accidentally erase a Prompt command with multiple arguments.

:Prompt A
:Prompt Str1
Combine the Prompts
:Prompt A,Str1

Error Conditions

  • ERR:INVALID occurs if this statement is used outside a program.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/prompt


The P►Rx( Command
PTORX.GIF

Command Summary

P►Rx( calculates the x-value (in Cartesian coordinates) given Polar coordinates.

Command Syntax

P►Rx(r,θ)

Menu Location

Press:

  1. 2nd ANGLE to access the angle menu.
  2. 7 to select P►Rx(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

P►Rx( (polar►rectangular x-coordinate) calculates the x-coordinate of a polar point. Polar coordinates are of the form (r,θ), where θ is the counterclockwise angle made with the positive x-axis, and r is the distance away from the origin (the point (0,0)). The conversion identity x=r*cos(θ) is used to calculate P►Rx(.

The value returned depends on whether the calculator is in radian or degree mode. A full rotation around a circle is 2π radians, which is equal to 360°. The conversion from radians to degrees is angle*180/π and from degrees to radians is angle*π/180. The P►Rx( command also accepts a list of points.

P►Rx(5,π/4)
    3.535533906
5*cos(π/4)
    3.535533906
P►Rx({1,2},{π/4,π/3})
    {.7071067812 1}

Advanced Uses

You can bypass the mode setting by using the ° (degree) and r (radian) symbols. This next command will return the same values no matter if your calculator is in degrees or radians:

P►Rx(1,{π/4^^r,60°})
    {.7071067812 .5}

Optimization

In most cases P►Rx(r,θ) can be replaced by r*cos(θ) to save a byte:

:P►Rx(5,π/12)
can be
:5cos(π/12)

Conversely, complicated expressions multiplied by a cosine factor can be simplified by using P►Rx(r,θ) instead.

:(A+BX)cos(π/5)
can be
:P►Rx(A+BX,π/5)

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/p-rx


The P►Ry( Command
PTORY.GIF

Command Summary

P►Ry( calculates the y-value (in Cartesian coordinates) given Polar coordinates.

Command Syntax

P►Ry(r,θ)

Menu Location

Press:

  1. 2nd ANGLE to access the angle menu.
  2. 8 to select P►Ry(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

P►Ry( (polar to rectangular y-coordinate) calculates the y-coordinate of a polar point. Polar coordinates are of the form (r,θ), where θ is the counterclockwise angle made with the positive x-axis, and r is the distance away from the origin (the point (0,0)). The conversion identity y=r*sin(θ) is used to calculate P►Ry(.

The value returned depends on whether the calculator is in radian or degree mode. A full rotation around a circle is 2π radians, which is equal to 360°. The conversion from radians to degrees is angle*180/π and from degrees to radians is angle*π/180. The P►Ry( command also accepts a list of points.

P►Ry(5,π/4)
    3.535533906
5*sin(π/4)
    3.535533906
P►Ry({1,2},{π/4,π/3})
    {.7071067812 1.732050808}

Advanced Uses

You can bypass the mode setting by using the ° (degree) and r (radian) symbols. This next command will return the same values no matter if your calculator is in degrees or radians:

P►Ry(1,{π/4^^r,60°})
    {.7071067812 .8660254038}

Optimization

In most cases P►Ry(r,θ) can be replaced by r*sin(θ) to save a byte:

:P►Ry(5,π/12)
can be
:5sin(π/12)

Conversely, complicated expressions multiplied by a sine factor can be simplified by using P►Ry(r,θ) instead.

:(A+BX)sin(π/5)
can be
:P►Ry(A+BX,π/5)

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/p-ry


The Pt-Change( Command
PT-CHANGE.gif

Command Summary

Toggles a point on the graph screen.

Command Syntax

Pt-Change(X,Y)

Menu Location

While editing a program press:

  1. 2nd PRGM to enter the DRAW menu
  2. RIGHT to enter the POINTS menu
  3. 3 to choose Pt-Change

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Pt-Change( command is used to toggle a point (a pixel on the screen) on the graph screen at the given (X,Y) coordinates. If the point is on, it will be turned off and vice versa. Pt-Change( is affected by the window settings, which means you have to change the window settings accordingly, otherwise the point won't show up correctly on the screen.

Pt-Change( can be an interactive command: when on the graph screen, you can select it from the draw menu, and rather than have to input coordinates, be able to draw directly on the screen. Since you can both draw and erase points easily with Pt-Change(, this use of it is often more convenient than the Pen tool.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pt-change


The PtChg Command

ptchg.png

Command Summary

Inverts a point on the graph screen.

Command Syntax

PtChg x, y

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The PtChg command inverts a point on the graph screen — drawing it if it isn't already there, and erasing it otherwise. It uses point coordinates, which means that the result is determined by window variables: the x-coordinate must be between xmin and xmax, and the y-coordinate must be between ymin and ymax (with (xmin,ymin) being the bottom left and (xmax,ymax) the top right corner).

Unlike pixel commands such as PxlChg, however, PtChg won't give an error if the coordinates happen to be outside these bounds — it simply won't have any effect.

Advanced Uses

PtChg can also be used with two lists of the same size. In that case, it will invert the points for every pair of elements (xlist[n], ylist[n]). This can be used as an alternative to plots (see NewPlot) to plot a set of points.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:ptchg


The PtOff Command

ptoff.png

Command Summary

Erases a point on the graph screen.

Command Syntax

PtOff x, y

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The PtOff command erases a point on the graph screen. It uses point coordinates, which means that the result is determined by window variables: the x-coordinate must be between xmin and xmax, and the y-coordinate must be between ymin and ymax (with (xmin,ymin) being the bottom left and (xmax,ymax) the top right corner).

Unlike pixel commands such as PxlOff, however, PtOff won't give an error if the coordinates happen to be outside these bounds — it simply won't have any effect.

Advanced Uses

PtOff can also be used with two lists of the same size. In that case, it will erase the points for every pair of elements (xlist[n], ylist[n]).

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:ptoff


The Pt-Off( Command
PT-OFF.gif

Command Summary

Turns off a point on the graph screen.

Command Syntax

Pt-Off(X,Y[,mark])

Menu Location

While editing a program press:

  1. 2nd PRGM to enter the DRAW menu
  2. RIGHT to enter the POINTS menu
  3. 2 to choose Pt-Off(

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Pt-Off( command is used to turn off a point (a pixel on the screen) on the graph screen at the given (X,Y) coordinates. Pt-Off( is affected by the window settings, which means you have to change the window settings accordingly, otherwise the point won't show up correctly on the screen.

Advanced Uses

The Pt-Off( command has an optional third argument that determines the shape of the point (its mark). The mark can be 1 (dot), 2 (3x3 box), 3 (3x3 cross), 6 (3x3 box), or 7 (3x3 cross). Note that by using the 3x3 shapes the X,Y coördinates will be the center of the shape and not the upperleft corner of the shape. You don't need to specify the mark when using the first mark because it is the default; also, any value that isn't 2, 3, 6, or 7 will be treated as the default of 1.

:Pt-Off(5,5,1
Remove Mark
:Pt-Off(5,5

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pt-off


The PtOn Command

pton.png

Command Summary

Draws a point on the graph screen.

Command Syntax

PtOn x, y
or
PtOn {x1, x2, x3}, {y1, y2, y3}

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The PtOn command draws a point on the graph screen. It uses point coordinates, which means that the result is determined by window variables: the x-coordinate must be between xmin and xmax, and the y-coordinate must be between ymin and ymax (with (xmin,ymin) being the bottom left and (xmax,ymax) the top right corner).

Unlike pixel commands such as PxlOn, however, PtOn won't give an error if the coordinates happen to be outside these bounds — it simply won't have any effect (exactly the same as the 83+ version of Pt-On).

Advanced Uses

PtOn can also be used with two lists of the same size. In that case, it will draw the points for every pair of elements (xlist[n], ylist[n]). This can be used as an alternative to plots (see NewPlot) to plot a set of points.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:pton


The Pt-On( Command
PT-ON.gif

Command Summary

Turns on a point on the graph screen.

Command Syntax

Pt-On(X,Y[,mark])

Menu Location

While editing a program press:

  1. 2nd PRGM to enter the DRAW menu
  2. RIGHT to enter the POINTS menu
  3. 1 to choose Pt-On(

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Pt-On( command is used to draw a point on the graph screen at the given (X,Y) coordinates. Pt-On( is affected by the window settings Xmin, Xmax, Ymin, and Ymax. Make sure to change these accordingly when using it in a program, otherwise, you don't know where the point will show up.

Advanced Uses

The Pt-On( command has an optional third argument that determines the shape of the point (its mark). The mark can be 1 (dot), 2 (3x3 box), 3 (3x3 cross), 6 (3x3 box), or 7 (3x3 cross). Note that by using the 3x3 shapes the X,Y coordinates will be the center of the shape and not the upperleft corner of the shape. You don't need to specify the mark when using the first mark because it is the default; also, any value that isn't 2, 3, 6, or 7 will be treated as the default of 1. Remember to use the same mark when turning a point off as you used to turn it on.

If you need to convert coordinates in pixel format into point coordinate format, it can easily be done with the following formula:

(X pixel coordinate*ΔX)-absolute value(Xmax)=X point
(Y pixel coordinate*ΔY)-absolute value(Ymax)=Y point

The ΔX and ΔY variables are available under "VARS", "Window", options 8 and 9. These two variables represent the number of points per pixel on the graph screen, so multiplying the pixel value by the ratio of points to pixels will give you the point value, you then subtract the Xmax/Ymax from this value to calibrate it to the center of the screen. This formula is useful in programs that use the pixel commands for their speed advantage, but need a point value for commands such as Circle( or Line(.

:Pt-On(5,5,1
should be
:Pt-On(5,5

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pt-on


The PwrReg Command
PWRREG.GIF

Command Summary

Calculates the best fit power curve through a set of points.

Command Syntax

PwrReg [x-list, y-list, [frequency], [equation]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. ALPHA A to select PwrReg, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

PwrReg tries to fit a power curve (y=a*xb) through a set of points. To use it, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points.

The calculator does this regression by taking the natural log ln( of the x- and of the y-coordinates (this isn't stored anywhere) and then doing a linear regression. The result, ln(y)=b*ln(x)+ln(a), is transformed into y=eln(a)*xb, which is a power curve. This algorithm shows that if any coordinates are negative or 0, the calculator will instantly quit with ERR:DOMAIN.

In its simplest form, PwrReg takes no arguments, and fits a power curve through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:LnReg

On the home screen, or as the last line of a program, this will display the equation of the curve: you'll be shown the format, y=a*x^b, and the values of a and b. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a, b, r, and r² will be set as well. These latter two variables will be displayed only if "Diagnostic Mode" is turned on (see DiagnosticOn and DiagnosticOff).

You don't have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:PwrReg ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the curve's equation is stored to this variable automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the equation will be in terms of X anyway, this doesn't make much sense.

An example of PwrReg with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:PwrReg ∟FAT,∟CALS,∟FREQ,Y1

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pwrreg


The Pxl-Change( Command
PXL-CHANGE.GIF

Command Summary

Toggles a pixel on the graph screen.

Command Syntax

Pxl-Change(row,column)

Menu Location

While editing a program press:

  1. 2nd PRGM to enter the DRAW menu
  2. RIGHT to enter the POINTS menu
  3. 6 to choose Pxl-Change(, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Pxl-Change( command is used to toggle the pixel at the given (Y,X) coordinates. If the pixel is on, it will be turned off and vice versa. Please note that the coordinates are switched around so that the row comes first and then the column — it's (Y,X) instead of (X,Y) like the Pt-Change( command. Also note that the row decreases as you go up which can confuse users.

In addition to being easier to use because it is not affected by the window settings (meaning you don't have to set them when using the command), Pxl-Change( is faster than its equivalent Pt-Change( command, so it should generally be used instead whenever possible.

Error Conditions

  • ERR:DOMAIN is triggered if the coordinates are not whole numbers or not in the right range ([0..62] for row, [0..94] for column). These bounds are also affected by split screen mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pxl-change


The PxlChg Command

pxlchg.png

Command Summary

Changes a pixel on the graph screen.

Command Syntax

PxlChg row, column

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The PxlChg command inverts a pixel on the graph screen: drawing it if it was erased, and erasing it otherwise. It uses pixel coordinates, which means that the result isn't affected by window variables like xmin and xmax: PxlChg P, Q will always change the pixel P rows down and Q columns across from the top left corner of the graph screen.

The range of possible values (anything outside this range will give an error) is:

  • 0..76 for the row and 0..158 for the column, on a TI-89 or TI-89 Titanium.
  • 0..102 for the row and 0..238 for the column, on a TI-92, TI-92 Plus, or Voyage 200.

Note that this doesn't match the output of getConfg() — the command is reliable for figuring out which of the two situations you're in, but the values it gives for window width/height are incorrect.

When in split screen mode, PxlChg still won't give an error as long as the values are in the regular range, but drawing a pixel off the screen will have no effect. The output of getConfg() will reflect the change in window size, but the values themselves still won't be correct.

In practice, PxlChg is the most useful of the pixel-toggling commands, because it can be used both to draw and to erase pixels.

Advanced Uses

PxlChg can also be used with two lists of the same size. In that case, it will change the pixels for every pair of elements (rowlist[n], collist[n]). This is a rarely-used alternative to a command like XorPic, with the one advantage that it doesn't require a picture variable (of course, if you had two such lists, you could easily use NewPic to create a picture variable).

Error Conditions

260 - Domain error happens when the pixel coordinates are not in the allowed range.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:pxlchg


The PxlOff Command

pxloff.png

Command Summary

Turns off a pixel on the graph screen.

Command Syntax

PxlOff row, column

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The PxlOff command erases a pixel on the graph screen. It uses pixel coordinates, which means that the result isn't affected by window variables like xmin and xmax: PxlOff P, Q will always erase the pixel P rows down and Q columns across from the top left corner of the graph screen.

The range of possible values (anything outside this range will give an error) is:

  • 0..76 for the row and 0..158 for the column, on a TI-89 or TI-89 Titanium.
  • 0..102 for the row and 0..238 for the column, on a TI-92, TI-92 Plus, or Voyage 200.

Note that this doesn't match the output of getConfg() — the command is reliable for figuring out which of the two situations you're in, but the values it gives for window width/height are incorrect.

When in split screen mode, PxlOff still won't give an error as long as the values are in the regular range, but erasing a pixel off the screen will have no effect. The output of getConfg() will reflect the change in window size, but the values themselves still won't be correct.

Advanced Uses

PxlOff can also be used with two lists of the same size. In that case, it will erase the pixels for every pair of elements (rowlist[n], collist[n]). This is a rarely-used alternative to a command like AndPic, with the one advantage that it doesn't require a picture variable (of course, if you had two such lists, you could easily use NewPic to create a picture variable).

Error Conditions

260 - Domain error happens when the pixel coordinates are not in the allowed range.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:pxloff


The Pxl-Off( Command
PXL-OFF.GIF

Command Summary

Turns off a pixel on the graph screen.

Command Syntax

Pxl-Off(row,column)

Menu Location

While editing a program press:

  1. 2nd PRGM to enter the DRAW menu
  2. RIGHT to enter the POINTS menu
  3. 5 to choose Pxl-Off(, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Pxl-Off( command is used to turn off the pixel at the given (Y,X) coordinates. Please note that the coordinates are switched around so that the row comes first and then the column — it's (Y,X) instead of (X,Y) like the Pt-Off( command. Also note that the (0,0) point is the upper left corner of the Graph screen.

In addition to being easier to use because it is not affected by the window settings (meaning you don't have to set them when using the command), Pxl-Off( is faster than its equivalent Pt-Off( command, so it should generally be used instead whenever possible.

Error Conditions

  • ERR:DOMAIN is triggered if the coordinates are not whole numbers or not in the right range ([0..62] for row, [0..94] for column). These bounds are also affected by split screen mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pxl-off


The PxlOn Command

pxlon.png

Command Summary

Turns on a pixel on the graph screen.

Command Syntax

PxlOn row, column

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The PxlOn command turns on a pixel on the graph screen. It uses pixel coordinates, which means that the result isn't affected by window variables like xmin and xmax: PxlOn P, Q will always turn on the pixel P rows down and Q columns across from the top left corner of the graph screen.

The range of possible values (anything outside this range will give an error) is:

  • 0..76 for the row and 0..158 for the column, on a TI-89 or TI-89 Titanium.
  • 0..102 for the row and 0..238 for the column, on a TI-92, TI-92 Plus, or Voyage 200.

Note that this doesn't match the output of getConfg() — the command is reliable for figuring out which of the two situations you're in, but the values it gives for window width/height are incorrect.

When in split screen mode, PxlOn still won't give an error as long as the values are in the regular range, but drawing a pixel off the screen will have no effect. The output of getConfg() will reflect the change in window size, but the values themselves still won't be correct.

Advanced Uses

PxlOn can also be used with two lists of the same size. In that case, it will turn on the pixels for every pair of elements (rowlist[n], collist[n]). This is a rarely-used alternative to a command like RclPic, with the one advantage that it doesn't require a picture variable (of course, if you had two such lists, you could easily use NewPic to create a picture variable).

Error Conditions

260 - Domain error happens when the pixel coordinates are not in the allowed range.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:pxlon


The Pxl-On( Command
PXL-ON.GIF

Command Summary

Turns on a pixel on the graph screen.

Command Syntax

Pxl-On(row,column)

Menu Location

While editing a program press:

  1. 2nd PRGM to enter the DRAW menu
  2. RIGHT to enter the POINTS menu
  3. 4 to choose Pxl-On(, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Pxl-On( command is used to turn on the pixel at the given (Y,X) coordinates. Please note that the coordinates are switched around so that the row comes first and then the column — it's (Y,X) unlike the (X,Y) of the Pt-On( command. Also note that the (0,0) point is the upper left corner of the Graph screen.

In addition to being easier to use because it is not affected by the window settings (meaning you don't have to set them when using the command), Pxl-On( is faster than its equivalent Pt-On( command, so it should generally be used instead whenever possible.

Error Conditions

  • ERR:DOMAIN is triggered if the coordinates are not whole numbers or not in the right range ([0..62] for row, [0..94] for column). These bounds are also affected by split screen mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pxl-on


The pxl-Test( Command
PXL-TEST.GIF

Command Summary

Tests a pixel on the graph screen to see if it is on or off.

Command Syntax

pxl-Test(Y,X)

Menu Location

While editing a program press:

  1. 2nd PRGM to enter the DRAW menu
  2. RIGHT to enter the POINTS menu
  3. 7 to choose pxl-Test(, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The pxl-Test( command is used to test a pixel at the given (Y,X) coordinates of the graph screen, to see whether it is on or off. One is returned if the pixel is on and zero is returned if the pixel is off. Please note that the coordinates are switched around so that the row comes first and then the column — it's (Y,X) instead of (X,Y). This command's coordinates are independent of the window settings.

You can store the result of pxl-Test( to a variable for later use, or use the command in a conditional or loop.

:Pxl-On(25,25
:If pxl-Test(25,25
:Disp "Pixel turned on!

Error Conditions

  • ERR:DOMAIN is triggered if the coordinates are not whole numbers or not in the right range ([0..62] for row, [0..94] for column). These bounds are also affected by split screen mode (Horiz)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/pxl-test


The QuadReg Command
QUADREG.GIF

Command Summary

Calculates the best fit quadratic through a set of points.

Command Syntax

QuadReg [x-list, y-list, [frequency list], [equation variable]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 5 to select QuadReg, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The QuadReg command can calculate the best fit quadratic through a set of points. To use it, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the nth element of one list matches up with the nth element of the other list. L₁ and L₂ are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points. You must have at least 3 points, because there are infinitely many quadratics that can go through 2 points or 1 point.

In its simplest form, QuadReg takes no arguments, and calculates a quadratic through the points in L₁ and L₂:

:{9,13,21,30,31,31,34→L₁
:{260,320,420,530,560,550,590→L₂
:QuadReg

On the home screen, or as the last line of a program, this will display the equation of the quadratic: you'll be shown the format, y=ax²+bx+c, and the values of a, b, and c. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a, b, c, and R² will be set as well. This latter variable will be displayed only if "Diagnostic Mode" is turned on (see DiagnosticOn and DiagnosticOff).

You don't have to do the regression on L₁ and L₂, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:QuadReg ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L₁ and L₂.

Finally, you can enter an equation variable (such as Y₁) after the command, so that the quadratic is stored to this equation automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the quadratic will be in terms of X anyway, this doesn't make much sense.

An example of QuadReg with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:QuadReg ∟FAT,∟CALS,∟FREQ,Y₁

Advanced

Note that even if a relationship is actually linear, since a quadratic regression has all the freedom of a linear regression and more, it will produce a better R² value, especially if the number of terms is small, and may lead you to (falsely) believe that a relationship is quadratic when it actually isn't. Take the correlation constant with a grain of salt, and consider if the fit is really that much better at the expense of added complexity, and if there's any reason to believe the relationship between the variables may be quadratic.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/quadreg


The QuartReg Command
QUARTREG.GIF

Command Summary

Calculates the best fit quartic equation through a set of points.

Command Syntax

QuartReg [x-list, y-list, [frequency list], [equation variable]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 7 to select QuartReg, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The QuartReg command can calculate the best fit quartic equation through a set of points. To use it, you must first store the points to two lists: one of the x-coordinates and one of the y-coordinates, ordered so that the Nth element of one list matches up with the Nth element of the other list. L1 and L2 are the default lists to use, and the List Editor (STAT > Edit…) is a useful window for entering the points. You must have at least 5 points, because there's infinitely many quadratics that can go through 4 points or less

In its simplest form, QuartReg takes no arguments, and calculates a quartic through the points in L1 and L2:

:{9,13,21,30,31,31,34→L1
:{260,320,420,530,560,550,590→L2
:QuartReg

On the home screen, or as the last line of a program, this will display the equation of the quartic: you'll be shown the format, y=ax4+bx3+cx2+dx+e, and the values of a, b, c, d, and e. It will also be stored in the RegEQ variable, but you won't be able to use this variable in a program - accessing it just pastes the equation wherever your cursor was. Finally, the statistical variables a, b, c, d, e, and R2 will be set as well. This latter variable will be displayed only if "Diagnostic Mode" is turned on (see DiagnosticOn and DiagnosticOff).

You don't have to do the regression on L1 and L2, but if you don't you'll have to enter the names of the lists after the command. For example:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:QuartReg ∟FAT,∟CALS

You can attach frequencies to points, for when a point occurs more than once, by supplying an additional argument - the frequency list. This list does not have to contain integer frequencies. If you add a frequency list, you must supply the names of the x-list and y-list as well, even when they're L1 and L2.

Finally, you can enter an equation variable (such as Y1) after the command, so that the quartic equation is stored to this variable automatically. This doesn't require you to supply the names of the lists, but if you do, the equation variable must come last. You can use polar, parametric, or sequential variables as well, but since the quadratic will be in terms of X anyway, this doesn't make much sense.

An example of QuartReg with all the optional arguments:

:{9,13,21,30,31,31,34→FAT
:{260,320,420,530,560,550,590→CALS
:{2,1,1,1,2,1,1→FREQ
:QuartReg ∟FAT,∟CALS,∟FREQ,Y1

Advanced

Note that even if a relationship is actually linear, since a quartic regression has all the freedom of a linear regression and much more, it will produce a better R2 value, especially if the number of points is small, and may lead you to (falsely) believe that a relationship is quartic when it actually isn't. An extreme example is the case of 5 points which are close to being on a line. The linear regression will be very good, but the quartic will seem even better - it will go through all 5 points and have an R2 value of 1. However, this doesn't make the 5 points special - any 5 (that don't have repeating x-values) will do! Take the correlation constant with a grain of salt, and consider if the fit is really that much better at the expense of much added complexity, and if there's any reason to believe the relationship between the variables may be quartic.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/quartreg


The r Command

radian.png

Command Summary

Converts an angle to radians, if necessary.

Command Syntax

angle r

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 2 to enter the Angle submenu.
  • Press 2 to select r.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

NOTE: Due to the limitations of the wiki markup language, the r command on this page does not appear as it would on the calculator. See Wiki Markup Limitations for more information.

The r symbol used after an angle makes sure the angle is interpreted as being in radians. If the calculator is already in radian mode, xr is equal to x; in degree mode, xr is equal to 180*x/π; and in gradian mode, xr is equal to 200*x/π.

If you're using radian angle measures extensively in a program, it's a better idea to use setMode() to switch to radian mode and not worry about this. However, there are two reasons you might want to use r:

  • If you need an angle in radians only once or twice, don't bother changing the mode setting.
  • In a function, you're forced to use r, since setMode() isn't valid in a function.

Make sure to use parentheses around an expression like (π/3)r, since π/3r will be interpreted as π/(3r), and the conversion will be done incorrectly.

In radian mode (no conversion is necessary, so no conversion is done):

:sin(π/6)
           1/2
:sin((π/6)^r)
           1/2
:π^r
           π

In degree mode:

:sin(π/6)
           sin(π/6)
:sin((π/6)^r)
           1/2
:π^r
           180

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:radian


The r (Radian Symbol) Command
RADIAN.GIF

Command Summary

If the calculator is in degree mode, the r (radian) symbol converts a radian angle to degrees.

Command Syntax

angler

Menu Location

Press:

  1. 2nd ANGLE to access the angle menu.
  2. 3 to select r, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

NOTE: Due to the limitations of the wiki markup language, the r command on this page does not appear as it would on the calculator. See Wiki Markup Limitations for more information.

Normally, when the calculator is in degree mode, the trigonometric functions only return values calculated in degrees. With the r symbol you can have the angle evaluated as if in radian mode because it converts the angle into degrees.

One full rotation around a circle is 2π radians, which is equal to 360°. To convert an angle in radians to degrees you multiply by 180/π, and to convert from degrees to radians multiply by π/180.

In degree mode:

sin(π)        \\sine of Pi degrees
    .0548036651
sin(π^^r)
    0

In radian mode:
sin(π)
    0
sin(π^^r)
    0        \\There's no difference when in radians

Optimization

When you only call the trig function once in a program and want it calculated in radians, instead of changing the mode you can just use ° to save one-byte (the newline from using the command Radian)

:Radian
:sin(X)
can be
:sin(X^^r)

Related Commands

  • ° (degree symbol)

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/radian-symbol


The Radian Command
RADIAN.GIF

Command Summary

Puts the calculator in Radian mode.

Command Syntax

Radian

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. Use arrows and ENTER to select Radian.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Radian command puts the calculator into Radian mode, where the inputs and/or outputs to trig functions are assumed to be radian angles.

Angles measured in radians range from 0 to 2π. They are defined as the arc length of the arc, on a unit circle (circle with radius 1), that corresponds to the angle when it is placed in the center. This definition actually only differs from degree measurements by a constant factor.

To convert from a degree angle to a radian angle, multiply by 180/π. To go the other way, and get a radian angle from a degree angle, multiply by π/180.

The following commands are affected by whether the calculator is in Radian or Degree mode:

The input is differently interpreted:

The output is differently expressed:

However, some commands are notably unaffected by angle mode, even though they involve angles, and this may cause confusion. This happens with the SinReg command, which assumes that the calculator is in Radian mode even when it's not. As a result, the regression model it generates will graph incorrectly in Degree mode.

Also, complex numbers in polar form are an endless source of confusion. The angle( command, as well as the polar display format, are affected by angle mode. However, complex exponentials (see the e^( command), defined as $\definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} e^{i\theta}=\cos\theta+i\sin\theta$, are evaluated as though in Radian mode, regardless of the angle mode. This gives mysterious results like the following:

Degree:re^θi
        Done
e^(πi)
        1e^(180i)
Ans=e^(180i)
        0 (false)

Overall, it's better to put your calculator in Radian mode when dealing with polar form of complex numbers, especially since no mathematician would ever use degrees for the purpose anyway.

Optimization

It's sometimes beneficial to use the r command instead of switching to Radian mode. The r symbol will make sure a number is interpreted as a radian angle, even in degree mode, so that, for example:

Degree
………………Done
sin(π)
……………….0548036651
sin(πr)
………………0

This is smaller when only one trig calculation needs to be done. Also, it doesn't change the user's settings, which are good to preserve whenever possible.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/radian-mode


The rand Command
RAND.GIF

Command Summary

Generates a random number between 0 and 1, or a list of such numbers. Can also be used to set the random number seed.

Command Syntax

rand

rand(# of numbers)

seed→rand

Menu Location

Press:

  1. MATH to access the math menu.
  2. LEFT to access the PRB submenu.
  3. ENTER to select rand.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

rand generates a uniformly-distributed pseudorandom number (this page and others will sometimes drop the pseudo- prefix for simplicity) between 0 and 1. rand(n) generates a list of n uniformly-distributed pseudorandom numbers between 0 and 1. seed→rand seeds (initializes) the built-in pseudorandom number generator. The factory default seed is 0.

L'Ecuyer's algorithm is used by TI calculators to generate pseudorandom numbers.

0→rand
     0
rand
     .9435974025
rand(2)
     {.908318861 .1466878292}

Note: Due to specifics of the random number generating algorithm, the smallest number possible to generate is slightly greater than 0. The largest number possible is actually 1, but since returning a result of 1 would mess up the output of randBin( and randNorm(, the actual value returned in such cases is 1-1.11e-12 (which is displayed as 1, and is "equal" to 1 for the purposes of the = command). To see 1, store 196164532 to rand and then run the random number generator.

Advanced Uses

To seed the random number generator, store a positive integer to rand (the command will ignore any decimals, and the sign of the number). Seeding the random number generator has several uses:

When writing a program that uses random numbers, you may add a 0→rand instruction to the beginning of the program — this ensures that the program's actions will be repeatable, making it easier to fix a bug. Just don't forget to take it out when you've finished writing the program.

Seeding the random number generator can also be used to create fairly secure (unbreakable without a computer) encryption. Pick a secret key, and store it to rand as a seed. Then, perform some randomly generated manipulations on the data you want to encode — for example, shifting each character of a string by a random number. Decoding the message is simple: store the secret key to rand and perform the opposite of those random operations. However, this is impossible to do if you don't know the secret key.


When seeding the random number generator, as above, you make every random number generated afterwards predictable. This may be problematic even if your program doesn't need random numbers, because other programs might. To prevent this, use the following code to save and restore "randomness":

:randInt(1,E9)→N

(code that involves seeding the RNG here)

:N→rand


Since generating random numbers is a fairly time-consuming operation, the rand(# of numbers) syntax is very effective at generating a delay in your program — just add the line:

:rand(N)

The bigger N is, the longer the delay. In relation to the commonly used For( loop delay, the number used in the rand( delay is about 10 times smaller. However, this code has a side effect of storing a list of random numbers to Ans, which may be undesirable. To avoid this, use this somewhat longer line:
:If dim(rand(N))

Despite the presence of an If statement, you don't have to worry about the next line being skipped, since dim(rand(N)) will always be true.

Error Conditions

  • ERR:DOMAIN if you try to generate a list of random numbers and the list length isn't an integer 1-999.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/rand


The rand() Command

rand.png

Command Summary

Generates a random number.

Command Syntax

rand() or rand(n)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 7 to enter the Probability submenu.
  • Press 4 to paste rand(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The rand() command generates a random number. It can be used in one of two ways:

  • rand() gives a random real number between 0 and 1.
  • rand(n) gives a random integer between 1 and n.

By adding or multiplying appropriately, you can change these bounds. For example, 10rand() gives a random real number between 0 and 10, and rand(9)-5 gives a random number between -4 and 4.

L'Ecuyer's algorithm is used by TI calculators to generate pseudorandom numbers.

:RandSeed 0
:rand()
           .943597402492
:rand()
           .908318860975
:rand(10)
           2

Advanced Uses

Using the RandSeed command makes the random numbers entirely predictable: after setting the random seed to some value, the same random numbers will be returned every time.

Error Conditions

260 - Domain error happens when the maximum number is 1014 or greater.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:rand


The randBin( Command
RANDBIN.GIF

Command Summary

Generates a random number with the binomial distribution.

Command Syntax

randBin(n,p,# simulations)

Menu Location

Press:

  1. MATH to access the math menu.
  2. LEFT to access the PRB submenu.
  3. 7 to select randBin(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

randBin(n,p) generates a pseudorandom integer between 0 and n inclusive according to the binomial distribution B(n,p) - that is, n trials of an event with probability of success p are performed, and the number of successes is returned. randBin(n,p,simulations) performs the above calculation simulations times, and returns a list of the results. The expected (average) result is n*p.

n should be an integer greater than or equal to 1, while p should be a real number between 0 and 1 inclusive.

seed→rand affects the output of randBin(

0→rand
     0
randBin(5,1/2
     2
randBin(5,1/2,10
     {3 3 2 4 3 2 2 2 4 3}

Formulas

The value of randBin( for a given seed can be expressed in terms of rand:

randBin(N,P)=sum(P>rand(N

This is identical to the output of randBin( in the sense that for the same seed, both expressions will generate the same random numbers.

Error Conditions

  • ERR:DOMAIN is triggered if the probability is not on the interval from 0 to 1.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/randbin


The randInt( Command
RANDINT.GIF

Command Summary

Generates a random integer between min and max, inclusive, or a list of such numbers.

Command Syntax

randInt(min,max[,# of numbers])

Menu Location

Press:

  1. MATH to access the math menu.
  2. LEFT to access the PRB submenu.
  3. 5 to select randInt(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

randInt(min,max) generates a uniformly-distributed pseudorandom integer between min and max inclusive. randInt(min,max,n) generates a list of n uniformly-distributed pseudorandom integers between min and max.

seed→rand affects the output of randInt(.

0→rand
     0
randInt(1,10)
     10
randInt(1,10,5)
     {10 2 6 5 8}

Optimization

When the lower bound of randInt( is 0, you can replace it with int(#rand to save space. For example:

:randInt(0,12
can be
:int(13rand

Similarly, if you don't want to include zero in the range, you can use a variant of 1-#int(#rand:

:1-2int(2rand

In this particular example, the only values that you will ever get are -1 or 1.

Formulas

The value of randInt( for a given seed can be expressed in terms of rand:

randInt(A,B)=

  • when A<B, A+int((B-A+1)rand
  • otherwise, B+int((A-B+1)rand

This is identical to the output of randInt( in the sense that for the same seed, both expressions will generate the same random numbers.

Error Conditions

  • ERR:DOMAIN is thrown if any of the arguments is a decimal.
  • ERR: DATA TYPE is given if you use imaginary numbers like 6i or something like Matrices or Lists. This error is used instead of ERR:DOMAIN for "i".

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/randint


The randIntNoRep( Command
randIntNoRep.gif

Command Summary

Used to create random lists

Command Syntax

randIntNoRep(start,end)

Menu Location

[Math][left][8]

Calculator Compatibility

OS 2.53MP and TI-84+/SE

Token Size

2 bytes (EF35h)

randIntNoRep( is used when you need to create a list of numbers in random order in which no integer is repeated. This command is useful for things such as simulating decks of cards. Commonly, before this command was introduced, the following code would shuffle a deck:

rand(52→L₂
seq(X,X,0,51→L₁
SortA(L₂,L₁

This result can now be achieved with the following code:
randIntNoRep(0,51→L₁

Advanced Uses

seed→rand affects the output of randIntNoRep(

What this does is quite simple. When you seed rand, then the next time you use randIntNoRep(, you will get a result that will be fairly random, but the same on all calculators. This allows several things to be possible, including password protection and encryption. For example, if you were to use the following code, you could encrypt and decrypt messages only if you use the same encryption value. In this example, Str1 contains the message:

Decode:

"ABCDEFGHIJKLMNOPQRSTUVWXYZ .!,0123456789→Str2
Input "CODE:",A
A→rand
randIntNoRep(1,length(Str2→L1
length(Str1→B
".
For(A,1,B
Ans+sub(Str2,sum(cumSum(L1=inString(Str2,sub(Str1,A,1)))),1
End
sub(Ans,2,B

Encode:
"ABCDEFGHIJKLMNOPQRSTUVWXYZ .!,0123456789→Str2
Input "CODE:",A
A→rand
length(Str2→C
randIntNoRep(1,Ans→L1
length(Str1→B
".
For(A,1,B
Ans+sub(Str2,L1(C+1-inString(Str2,sub(Str1,A,1))),1
End
sub(Ans,2,B

The output strings are in Ans

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/randintnorep


The randM( Command
RANDM.GIF

Command Summary

Creates a matrix of specified size with the entries random integers from -9 to 9.

Command Syntax

randM(# rows, # columns)

Menu Location

Press:

  1. MATRX (TI-83) or 2nd MATRX (TI-83+ or higher) to access the matrix menu
  2. RIGHT to access the MATH submenu.
  3. 6 to select randM(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

randM(M, N) generates an M by N matrix whose entries are pseudorandom integers between -9 and 9 inclusive.

seed→rand affects the output of randM(.

0→rand
    0
randM(3,3)
    [[9  -3 -9]
     [4  -2 0 ]
     [-7 8  8 ]]

If you actually cared about the bounds of the random numbers, this command would not be very useful, since it's hard to manipulate the matrix to yield uniformly spread random numbers in a different range.

Formulas

The entries of randM( are actually the outputs of successive calls to randInt(-9,9), filled in starting at the bottom right and moving left across each row from the last row to the first.

Error Conditions

  • ERR:INVALID DIM is thrown if the number of rows or columns of the matrix isn't an integer 1-99.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/randm


The randMat() Command

randmat.png

Command Summary

Generates a random matrix.

Command Syntax

randMat(rows,columns

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 7 to enter the Probability submenu.
  • Press 7 to select randMat(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The randMat() command generates a random matrix: randMat(rows,columns) generates a rows by columns matrix whose entries are random integers between -9 and 9.

:RandSeed 0
:randM(3,2)
           [4  -2]
           [0  -7]
           [8  8 ]

Advanced Uses

Using the RandSeed command makes the random matrix entirely predictable: after setting the random seed to some value, the same random matrix will be returned every time (assuming the size is the same). See the RandSeed page for details of how random numbers are generated.

Error Conditions

260 - Domain error happens when the rows and columns parameters aren't positive integers..

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:randmat


The randNorm( Command
RANDNORM.GIF

Command Summary

Generates a random normally-distributed number with specified mean and standard deviation.

Command Syntax

randNorm(µ,σ,[n])

Menu Location

Press:

  1. MATH to access the math menu.
  2. LEFT to access the PRB submenu.
  3. 6 to select randNorm(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

randNorm(µ,σ) generates a normally-distributed pseudorandom number with mean µ and standard deviation σ. The result returned will most probably be within the range µ±3σ. randNorm(µ,σ,n) generates a list of n normally-distributed pseudorandom numbers with mean µ and standard deviation σ.

seed→rand affects the output of randNorm(.

0→rand
     0
randNorm(0,1)
     -1.585709623
randNorm(0,1,3)
     {-1.330473604 1.05074514 -.0368606663}

Although a theoretical normally distributed variable could take on any real value, numbers on a calculator have a limited precision, which leads to a maximum range of approximately µ±7.02σ for values of randNorm(.

Optimization

When the mean is 0 and the standard deviation 1, invNorm(rand) and invNorm(rand(N)) save space over randNorm(0,1) and randNorm(0,1,N) respectively.

Formulas

The value of randNorm( for a given seed can be expressed in terms of rand:

randNorm(µ,σ)=µ-σinvNorm(rand

This is identical to the output of randNorm( in the sense that for the same seed, both expressions will generate the same random numbers.

The following formula can be used to get a target interval where A and B are two real intervals.

µ=(A+B)/2
σ=(-A+B)/6

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/randnorm


The randNorm() Command

randnorm.png

Command Summary

Generates a random normally-distributed number.

Command Syntax

randNorm(mean,std-dev)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 7 to enter the Probability submenu.
  • Press 5 to select randNorm(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The randNorm() command generates a random number that is normally distributed, with a given mean (first parameter) and standard deviation (second parameter). This means that on average, randNorm(x,y) will give a result of about x; it's 95% certain to be within 2*y of x.

See rand() and RandSeed for more details on the random number generator.

Formula

The formula for randNorm() is different from the one used by the TI-83 series. To generate normally-distributed values from the output of rand(), the calculator uses the polar form of the Box-Muller transform. The algorithm goes as follows:

First, generate two uniformly distributed numbers u and v in [-1,1]. Keep doing this until the result lies in the unit circle; the point (0,0), though it's unlikely to occur, is discarded as well. Let s equal u2+v2.

Usually, Box-Muller is used to produce two normally-distributed random numbers, by the formula below. The TI only uses the second of the results:

(1)
\begin{align} z_0=u\cdot\sqrt{\frac{-2\ln s}{s}}\hspace{2em}z_1=v\cdot\sqrt{\frac{-2\ln s}{s}} \end{align}

The result is distributed according to the standard normal distribution: that is, with mean 0 and standard deviation 1. It's easy to get any other normal distribution by scaling: multiplying by the standard deviation, and then adding the mean.

In TI-Basic, the code for randNorm(μ,σ) would be:

:Loop
: 2*rand()-1→u
: 2*rand()-1→v
: u^2+v^2→s
: If 0<s and s<1
:  Return μ+σ*v*√(-2*ln(s)/s)
:EndLoop

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:randnorm


The randPoly() Command

randpoly.png

Command Summary

Generates a random polynomial.

Command Syntax

randPoly(var,deg)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 7 to enter the Probability submenu.
  • Press 8 to select randPoly(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The randPoly() command generates a random polynomial. randPoly(var,deg) generates a random polynomial in variable var of degree deg. The coefficients of each power of var are random integers from -9 to 9.

:RandSeed 0
:randPoly(x,5)
           4*x^5-2*x^4-7*x^2+8*x+8

Advanced Uses

Using the RandSeed command makes the resulting polynomial entirely predictable: every time you set the random seed to some variable, you will get the same random coefficients afterwards. Also see RandSeed for details of how random numbers are generated.

Error Conditions

260 - Domain error happens when the value of deg is not between 0 and 99.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:randpoly


The RandSeed Command

randseed.png

Command Summary

Seeds the random number generator.

Command Syntax

RandSeed value

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 7 to enter the Probability submenu.
  • Press 6 to select RandSeed.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The RandSeed command seeds the random number generator. The value you use should be a positive integer: the sign and any decimals will be simply ignored.

To explain what this means, first you have to understand how pseudo-random number generators work. Every time a command like rand() is called the calculator gives a different number — this means that the calculator must keep some variable around that changes when rand() is called. This variable is called the seed. Generating a random number is done as follows:

  1. To get the number itself, apply some function that takes the seed to a real number between 0 and 1 (for a simple rand() call).
  2. If a different type of random number is needed (e.g. a random integer), the real number 0..1 is adjusted in some way.
  3. The seed itself is updated by some carefully chosen mathematical operation.

"Seeding" the random number generator means setting the seed to some specific value. This is done for two reasons:

  • To ensure randomness, you might seed the random generator with the current time — that way, it's guaranteed to be different every second of every day.
  • Every time you seed the random number generator with a specific number, the random numbers that follow will be the same. For example, the following output is guaranteed to be the same on all calculators every time (except for formatting):
:RandSeed 100
:rand()
           .556077
:rand()
           .590054

Advanced Uses

Seed the RNG with the current time by using the following command:

:RandSeed startTmr()

The random number generator is very popular as an encryption method to implement on calculators. This is done as follows:

  1. Use the encryption key as a random number seed.
  2. Do something to the text to be encrypted that involves random numbers (e.g. a randomly generated One-Time Pad)
  3. To decrypt, use the encryption key as a seed, and reverse the operation above.

Most of the security of this method lies in the obscurity of the random number generator. Someone that has read this page (or someone from Texas Instruments) could break the code in a matter of seconds on a computer; and if they knew anything at all about the message, they could probably break the code with just a calculator.


In general, after you mess with the random number seed, you must 'restore randomness' somehow — otherwise, every time you run that program, random numbers will be the same afterwards every time. Using startTmr() as above is one way of doing so; another is generating a random integer before you run RandSeed, and using it as the seed at the end. For example:

:rand(10^10) →r
:RandSeed 0

(code with predictable random numbers)

:RandSeed r

The RNG Algorithm

The algorithm used by the calculator to generate random numbers is known as L'Ecuyer's algorithm. This particular implementation works as follows.

The following constants are used:

:2147483563→mod1
:2147483399→mod2
:40014→mult1
:40692→mult2

RandSeed n is equivalent to the following code:

:abs(int(n))→n
:If n=0 Then
: 12345→seed1
: 67890→seed2
:Else
: mod(mult1*n,mod1)→seed1
: mod(n,mod2)→seed2
:EndIf

rand() is equivalent to the following code:

:Local result
:mod(seed1*mult1,mod1)→seed1
:mod(seed2*mult2,mod2)→seed2
:(seed1-seed2)/mod1→result
:If result<0
: result+1→result
:Return result

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:randseed


The RclPic command

rclpic.png

Command Summary

Recalls a picture variable and the graph screen at [row][, column]

Command Syntax

RclPic picVar,[row][, column]

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

This command is used to recall (open) a picture you have saved on your calculator. This is normally used in programs, because you can open pictures from the graph when you are not running a program. It is very useful for sprites as well, as it can recall a picture variable on top of a background, without deleting any of the background. In a program, however, you can recall a different picture for a different input, as shown below:

:If a=16
:RclPic 2
:Else
:RclPic 3

Error Conditions

260 - Domain error happens when the [row][,column] argument is outside the screen range..

960 - Undefined variable happens when the picture variable specified does not exist..

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:rclpic


The real( Command
REAL.GIF

Command Summary

Returns the real part of a complex value.

Command Syntax

real(value)

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT, RIGHT to access the CPX (complex) submenu.
  3. 2 to select real(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

real(z) returns the real part of the complex number z. If z is represented as x+iy where x and y are both real, real(z) returns x. Also works on a list of complex numbers.

real(3+4i)
     3

Advanced Uses

The real( command is expanded by several assembly libraries (such as xLIB and Omnicalc) to call their own routines. If xLib is installed, then real( will no longer work as intended even in programs that want to use it for its intended purpose.

If you actually want to take the real part of a complex number, and want the program to work with one of these assembly libraries, you could use the imag( command instead - real(Z) is equivalent to imag(Zi). Alternatively, you could tell people using your program to uninstall xLIB or Omnicalc first.

If a program you downloaded has an error and 2:Goto takes you to a line with real( and a bunch of arguments, this is probably because the program uses Omnicalc or xLIB which you don't have installed.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/real-func


The Real Command
REAL.GIF

Command Summary

Enables real number only mode.

Command Syntax

Real

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. Use arrows and ENTER to select Real.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Real command puts the calculator in real number-only mode. This shouldn't be taken quite literally, as you can still type in i to get complex numbers, and do operations with them (they will be displayed as in a+bi mode, in that case). However, any operation done with real numbers that comes out to a complex result, such as taking the square root of a negative number, will throw a ERR:NONREAL ANS error.

There is no real advantage to using Real mode over a+bi mode — it just adds another error condition that wouldn't be triggered otherwise. However, it is the default setting, and so there's a good chance that the calculator will be in Real mode when someone runs your program. Thus, when using complex numbers implicitly (such as in a quadratic equation solver) you should do something about this.

Advanced Uses

Rather than switch to a+bi mode, you might want to force the calculations to use complex numbers by making the original argument complex. The general way to do this is by adding +0i to the number. However, there may be an optimization in any particular case. See the quadratic formula routine for a good example of this.

Real
        Done
√(-1)    
        (causes an error)
√(-1+0i)        
        i

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/real-mode


The RecallGDB Command
RECALLGDB.GIF

Command Summary

Recalls graph settings from a GDB (Graph DataBase) variable

Command Syntax

RecallGDB number

Menu Location

Press:

  1. 2nd DRAW to access the draw menu.
  2. LEFT to access the STO menu.
  3. 4 to select RecallGDB, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The RecallGDB command recalls graph settings a GDB (Graph DataBase) variable, one of GDB1, GDB2, …, GDB0 (as indicated by the argument). These settings can be stored to a GDB using the StoreGDB command.

The settings stored in a GDB include:

  • The graphing mode currently enabled.
  • All equations in the current graphing mode, but NOT other graphing modes.
  • All window variables applicable to the current graphing mode. This does not include zoom variables, table settings, or irrelevant variables such as Tmin when in function mode.
  • The menu settings relevant to graphing (everything in the 2nd FORMAT menu, as well as Connected/Dot and Sequential/Simul settings in the MODE menu)

The number passed to RecallGDB must be one of 0 through 9. It has to be a number: RecallGDB X will not work, even if X contains a value 0 through 9.

Advanced Uses

The StoreGDB and RecallGDB variables are useful in cleaning up after a program finishes running, preserving the user's settings. If your program heavily relies on the graph screen, it may end up editing window size or other graph settings, which the user might want to be saved. This is easily done:

Add StoreGDB 1 (or any other number) to the beginning of your program.

Then, feel free to edit any graph settings you like.

At the end of your program, add RecallGDB 1, followed by DelVar GDB1, to recall the graph settings stored at the beginning.

GDBs can also be useful in adding extra string storage. You can store strings to the Yn variables, and back them up in a GDB; to retrieve them later, recall the GDB and use Equ►String( to store the equations to the strings again.

Error Conditions

  • ERR:DATA TYPE is thrown if the argument is not a number 0 through 9.
  • ERR:UNDEFINED is thrown if the requested GDB does not exist.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/recallgdb


The RecallPic Command
RECALLPIC.GIF

Command Summary

Recalls a saved picture (one of Pic1, Pic2, …, Pic0) to the graph screen.

Command Syntax

RecallPic number

Menu Location

Press:

  1. 2nd DRAW to access the draw menu.
  2. LEFT to access the STO submenu.
  3. 2 to select RecallPic, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

RecallPic draws a saved picture to the graph screen (to save a picture, draw it on the graph screen, then save it with StorePic). If something is already drawn on the graph screen, RecallPic will draw new pixels where needed, but it will not erase anything. As a result, you often want to ClrDraw before recalling a picture.

The number passed to RecallPic must be one of 0 through 9. It has to be a number: RecallPic X will not work, even if X contains a value 0 through 9.

Advanced Uses

A combination of StorePic and RecallPic can be used to maintain a background over which another sprite moves:

  1. Draw the background, and save it to a picture file with StorePic.
  2. Next, draw the sprite to the screen.
  3. When you want to move the sprite, erase it, then use RecallPic to draw the background again.
  4. Then draw the sprite to its new location on the screen again (this can be done before or after using RecallPic).

Also, if a screen in your program takes more than a second to draw, and is displayed several times, you might want to consider storing it to a picture the first time it's drawn, and then recalling it every next time you want to draw it.

Error Conditions

  • ERR:DATA TYPE is thrown if the argument is not a number 0 through 9.
  • ERR:UNDEFINED is thrown if the requested picture does not exist.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/recallpic


The ►Rect Command
RECT.GIF

Command Summary

Formats a complex value in rectangular form when displaying it.

Command Syntax

value►Rect

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT RIGHT to access the CPX submenu.
  3. 6 to select ►Rect, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The ►Rect command can be used when displaying a complex number on the home screen, or with the Disp and Pause commands. It will then format the number as though a+bi mode were enabled, even when it's not. It also works with lists.

i►Polar
    1e^(1.570796327i)
Ans►Rect
    i

It will also work when displaying a number by putting it on the last line of a program by itself. It does not work with Output(, Text(, or any other more complicated display commands.

To actually separate a number into the components of rectangular form, use real( and imag(.

Error Conditions

  • ERR:SYNTAX is thrown if the command is used somewhere other than the allowed display commands.
  • ERR:DATA TYPE is thrown if the value is real.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/rect


The RectGC Command
RECTGC.GIF

Command Summary

Sets the calculator to display point coordinates using rectangular (Cartesian) coordinates.

Command Syntax

RectGC

Menu Location

Press:

  1. 2nd FORMAT to access the graph format screen
  2. Use arrows and ENTER to select RectGC.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The RectGC ("Rectangular Grid Coordinates") command (like its opposite, the PolarGC) command, affects how the coordinates of a point on the graph screen are displayed. When RectGC is enabled, the coordinates of a point are displayed as (X,Y).

The X and Y coordinates of a point are interpreted as the horizontal and vertical distance from the origin (the point (0,0)) Up and right are positive directions, while down and left are negative. For example, the point (1,-2) — that is, the point with x-coordinate 1 and y-coordinate -2 — is one horizontal unit right and two horizontal units down from (0,0).

Of course, coordinates are only displayed with the CoordOn setting; however, with CoordOff, RectGC and PolarGC are still useful, because in a variety of cases, the coordinates of a point are also stored to variables. With RectGC enabled, they are stored to X and Y.

Advanced

The following situations involve storing coordinates of a point to variables:

  • Graphing an equation
  • Tracing an equation or plot
  • Moving the cursor on the graph screen
  • Using the interactive mode of one of the 2nd DRAW commands
  • Using one of DrawF, DrawInv, or Tangent(
  • Anything in the 2nd CALC menu.

Naturally, any command like Input or Select( which involves the above, will also store coordinates of a point.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/rectgc


The ref( Command
REF.GIF

Command Summary

Puts a matrix into row-echelon form.

Command Syntax

ref(matrix)

Menu Location

Press:

  1. MATRX (on the TI-83) or 2nd MATRX (TI-83+ or higher) to access the matrix menu.
  2. RIGHT to access the MATH submenu.
  3. ALPHA A to select ref(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

Given a matrix with at least as many columns as it has rows, the ref( command uses a technique called Gaussian elimination to put the matrix into row-echelon form.

This means that the leftmost N columns (if the matrix has N rows) of the matrix are upper triangular - all entries below the main diagonal are zero. What's more, every entry on the main diagonal is either 0 or 1.

[[1,2,5,0][2,2,1,2][3,4,6,2]]
    [[1 2 5 0]
     [2 2 1 2]
     [3 4 6 2]
ref(Ans)►Frac
    [[1 4/3 2   2/3]
     [0 1   9/2 -1 ]
     [0 0   0   0  ]]

Advanced Uses

In theory, a system of linear equations in N variables can be solved using the ref( command - an equation of the form $a_1x_1+\dots + a_nx_n = b$ becomes a row $a_1, \dots, a_n, b$, and is put into the matrix. If there is a sufficient number of conditions, the last row of the reduced matrix will give you the value of the last variable, and back-substitution will give you the others.

In practice, it's easier to use rref( instead for the same purpose.

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/ref


The remain() Command

remain.png

Command Summary

Returns the remainder of a division.

Command Syntax

remain(dividend,divisor)

Menu Location

  • Press 2nd MATH to enter the math popup menu.
  • Press 1 to enter the Number submenu.
  • Press A to select remain(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The remain() command returns the remainder of a division: remain(A,B) is calculated as A-B*intDiv(A,B) which in turn is equivalent to A-B*iPart(A/B). Although this operation is most useful for dividing whole numbers, this definition works for any number, whole or decimal, real or complex. Additionally, remain(X,0) is defined as X.

The related mod() command returns the same results for positive numbers, however, they disagree when negative integers enter the mix. The result of mod() is defined just as remain(), but with int() instead of iPart(). This means that remain() gives a negative answer if the dividend is negative, and mod() gives a negative answer if the divisor is negative.

:remain(125,3)
           2
:remain(-125,3)
           -2
:remain(2*i+1,i+1)
           i

The remain() command also works for lists and matrices. Used with a list or matrix and a number, remain() is applied to the number paired with every element of the list or matrix. Used with two lists or two matrices, which must match in size, remain() is applied to matching elements of the list or matrix.

Advanced Uses

Use intDiv() and remain() for the quotient and remainder results of long division, respectively.

Error Conditions

240 - Dimension mismatch happens when two list or matrix arguments don't match in size.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:remain


The Repeat Command
REPEAT_ANIMATED.GIF

Command Summary

Loops through a block of code until the condition is true. Always loops at least once.

Command Syntax

Repeat condition
statement(s)
End

Menu Location

While editing a program press:

  1. PRGM to enter the PRGM menu
  2. 6 to choose Repeat, or use arrows
  3. 7 to choose End, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

A Repeat loop executes a block of commands between the Repeat and End commands until the specified condition is true. The condition is tested at the end of the loop (when the End command is encountered), so the loop will always be executed at least once. This means that you sometimes don't have to declare or initialize the variables in the condition before the loop.

After each time the Repeat loop is executed, the condition is checked to see if it is true. If it is true, then the loop is exited and program execution continues after the End command. If the condition is false, the loop is executed again.

Advanced Uses

When using Repeat loops, you have to provide the code to break out of the loop (it isn't built into the loop). If there is no code that ends the loop, then you will have an infinite loop. An infinite loop just keeps executing, until you have to manually exit the loop (by pressing the ON key). In the case that you actually want an infinite loop, you can just use 0 as the condition. Because 0 is always false (based on Boolean Logic), the loop will never end.

:Repeat 0
:statement(s)
:End

Each time the program enters a Repeat block, the calculator uses 35+(size of the condition) bytes of memory to keep track of this. This memory is given back to you as soon as the program reaches End. This isn't really a problem unless you're low on RAM, or have a lot of nested Repeat statements. However, if you use Goto to jump out of a Repeat block, you lose those bytes for as long as the program is running — and if you keep doing this, you might easily run out of memory, resulting in ERR:MEMORY.

Optimization

The Ans variable (last answer) is a temporary variable that can hold any variable. Ans is changed when there is an expression or variable storage or when pausing with the Pause command. It is mostly useful when you are just manipulating one variable. To use Ans just put an expression on a line by itself; it will automatically be stored to Ans. You can then change the expressions on the next line where the variable was called and put Ans there instead.

Because Repeat loops are executed at least once, you can sometimes put Ans in the condition instead of the variable.

:Repeat A
:getKey→A
:End
can be
:Repeat Ans
:getKey→A
:End

Command Timings

When deciding whether to use a Repeat loop, as opposed to a For or While loop, it's good to know how Repeat loops stack up against them. This comparison comes from the Code Timings page showing the speeds of the three different kinds of loops:

Format Bars Pixels
For(A,0,2000
End
4 bars + 4 pixels 36
Delvar A
While A≤2000
A+1→A
End
23 bars 184
Delvar A
Repeat A>2000
A+1→A
End
22 bars + 7 pixels 183

The general conclusion you can take away from this table is that For( loops should be used when speed is a priority, and then you should use Repeat or While loops when the appropriate circumstance comes up. Each kind of loop has its own place, so it's still good to know how to use all three of them.

Error Conditions

  • ERR:INVALID occurs if this statement is used outside a program.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/repeat


The Return Command
RETURN_ANIMATED.GIF

Command Summary

Stops the program and returns the user to the home screen. If the program is a subprogram, however, it just stops the subprogram and returns program execution to the parent program.

Command Syntax

Return

Menu Location

Press:

  1. PRGM to enter the PRGM menu
  2. ALPHA SIN to choose Return, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

When the Return command is used in a program it exits the program (terminating the program execution) and returns the user to the home screen. If it is encountered within loops, the loops will be stopped.

There is some distinction when using Return with subprograms: the Return command will stop the program execution of the subprogram, and program execution will go back to the calling program, continuing right after the subprogram call. If this functionality is not desired, then you should use the Stop command instead. Generally, though, you should use Return instead of Stop.

:ClrHome
:Input "Guess:",A
:Stop
Replace Stop with Return
:ClrHome
:Input "Guess:",A
:Return

Optimization

You don't have to put a Return command at the end of a program or subprogram if you can organize the program so that it just naturally quits. When the calculator reaches the end of a program, it will automatically stop executing as if it had encountered a Return command (the Return is implied).

:ClrHome
:Input "Guess:",A
:Return
Remove the Return
:ClrHome
:Input "Guess:",A

Error Conditions

  • ERR:INVALID occurs if this statement is used outside a program.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/return


The re^θi Command
RETHETAI.GIF

Command Summary

Puts the calculator into re^θi mode.

Command Syntax

re^θi

Menu Location

Press:

  1. MODE to access the mode menu.
  2. Use the arrow keys and ENTER to select re^θi

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The re^θi command puts the calculator into polar complex number mode. This means that:

  • Taking square roots of negative numbers, and similar operations, no longer returns an error.
  • Complex results are displayed in the form re^(θi) (hence the name of the command)

The mathematical underpinning of this complex number format is due to the fact that if (x,y) is a point in the plane using the normal coordinates, it can also be represented using coordinates (r,θ) where r is the distance from the origin and θ is the angle that the line segment to the point from the origin makes to the positive x-axis (see Polar and PolarGC for more information on polar coordinates and graphing). What does this have to do with complex numbers? Simple: if x+yi is a complex number in normal (rectangular) form, and re^(θi) is the same number in polar form, then (x,y) and (r,θ) represent the same point in the plane.

Of course, that has a lot to do with how you define imaginary exponents, which isn't that obvious.

An equivalent form to polar form is the form r[cos(θ)+isin(θ)].

Unfortunately, the calculator seems to have some confusion about the use of degree and radian angle measures for θ in this mode (the answer is: you can only use radians — degrees make no sense with complex exponents). When calculating a value re^(θi) by using the e^( command and plugging in numbers, the calculator assumes θ is a radian angle, whether it's in Degree or Radian mode. However, when displaying a complex number as re^(θi), the calculator will display θ in radian or degree measure, whichever is enabled. This may lead to such pathological output as:

Degree:re^θi
        Done
e^(πi)
        1e^(180i)
Ans=e^(180i)
        0 (false)

It's recommended, then, to use Radian mode whenever you're in re^θi mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/re-thetai


The right() Command

right.png

Command Summary

Returns a subsection from the right of a list or string, or the right hand side of an equation.

Command Syntax

right(equation)
right(list-or-string,length)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 3 to enter the List submenu.
  • Press B to select right(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

When applied to a list or a string, right(x,length) gets the last (right-most) length elements/characters of x.

When applied to an equation (such as x=5) or an inequality (such as x<3), right() returns the right-hand side of the equation. This only works for equations that don't get simplified: right(2+2=4) will not work, because 2+2=4 will return 'true' first.

:right({1,2,3,4,5},3)
           {3  4  5}
:right("TI-Basic Developer",9)
           "Developer"
:right(x^2+2x+1>0)
           0
:right({1,2,3,4,5},0)
           {}

Error Conditions

260 - Domain error happens when the argument is not a list, string, or equation, or is an equation that has simplified.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:right


The root() Command

root.png

Command Summary

Takes the nth root of a value.

Command Syntax

root(value,n)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 1 to enter the Number submenu.
  • Press D to select root(.

Calculator Compatibility

This command requires a TI-89 Titanium or Voyage 200 calculator with AMS version 3.10 or higher.

Token Size

2 bytes

The root() command takes nth roots: root(x,2) is the square root of x, root(x,3) is the cubic root, etc. (n doesn't have to be a whole number, or even real). Since root(x,n) is equivalent to x^(1/n), there was never any real need for this command, but it was added in the last AMS update for the Voyage 200 and TI-89 Titanium because users complained about not being able to do this calculation.

As far as complex roots are concerned: if taking a root of a real number, root() will return the real branch if there is one. If taking the root of a complex number, it will always return the principal branch.

:root(x,2)
           √(x)
:root(1024,10)
           2

Advanced Uses

The command uses the same routines as the ^ operator, so it works in all the same ways. This means it can be applied to lists (element-wise), and to matrices either through repeated multiplication (e.g. if taking the 1/100th root of a matrix, which ends up being its 100th power) or by diagonalizing the matrix first (see Matrices and Their Commands for mor information about this method). If you want to take the nth root of every element of a matrix, use the .^ command.

Optimization

You can save a few bytes of space by using root(x,n) instead of x^(1/n); however, this optimization is a bit dodgy. It requires AMS 3.10 to use, so if you're planning on releasing the program anywhere, it will only work on the TI-89 Titanium and the Voyage 200, and even then it might require updating the OS. It's probably not worth it, unless the program is for personal use only.

Error Conditions

230 - Dimension happens when non-square matrices are used with root().

230 - Domain error happens when a matrix is raised to an integer power not in the range -32768..32767.

665 - Matrix not diagonalizable happens when diagonalization (used to compute most uses of root() with matrices) fails.

800 - Non-real result happens when there is no real result to return, and the calculator is in real number mode.

890 - Singular matrix happens when raising a matrix with no inverse to a negative power.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:root


The rotate() Command

rotate.png

Command Summary

Rotates a string, list, or binary integer.

Command Syntax

rotate(object,places)

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press E to enter the Base submenu.
  • Press C to select rotate(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

When rotate() is applied to lists or strings, it moves every element or character over, moving the displaced elements over to the other end. By default, it shifts everything right one space, and moves the rightmost element to the beginning.

A second argument gives the direction and number of places to rotate the list or string. Positive numbers are rotations to the left, and negative numbers are rotation to the right, so the default action rotate(object) is equivalent to rotate(object,-1). Here are some examples:

:rotate({1,2,3,4,5})
           {5  1  2  3  4}
:rotate("Hello")
           "oHell"
:rotate({1,2,3,4,5},2)
           {3  4  5  1  2}
:rotate("TI-Basic",-3)
           "sicTI-Ba"

rotate() can also be used on integers, treating them as a sequence of bits (this makes the most sense when expressing them in binary). In this case, the integer is expressed as a 32-bit signed integer (larger integers are truncated), whose bits are then rotated.

As with lists and strings, the default action of rotate() is to rotate the integer one position right. A second argument gives the direction and number of places to rotate the list or string. Positive numbers are rotations to the left, and negative numbers are rotations to the right.

:shift(0b00000000000000000000000011111111)▶Bin
           0b10000000000000000000000001111111
:rotate(1,10)
           1024

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:rotate


The round() command

Round.png

Command Summary

Truncates a number to a specified number of decimal places.

Command Syntax

round(value[,number of decimal places to round to])

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 1 to enter the Number submenu.
  • Press 3 to select round(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The round command takes whatever value you give it, and it rounds the value to a given number of decimal places. For instance round(9.7,0) will return 10, since rounding to 0 decimal places will return the closest whole number. Another example would be if you entered round(5.46338,3) which would return 5.463, since it rounded 5.46338 to 3 decimal places. The round function can round 0 to 12 decimal places, and if you enter a value outside that range, you will get a domain error. Strangely enough, if you enter an imaginary number into the round() command, nothing happens and the calculator returns the same function in a simplified form.

:round(99.35847475,5)
:         99.35847
:round(4.392i,2)
:         round(4.392*i,2.)
:round(2.348972,2i)
:         round(2.348972,2*i)

Unexpected results

Your calculator may also round, say for instance if you do this:

:round(2.4573485645,11)

If your calculator is set to float or to fix at 10 or less, the calculator will round the number that comes out of the function. The function above should return 2.4573485645, since that is less than 11 digits, but if your calculator is set to "Float 6" it will return 2.457349 instead of what you expected.

Error Conditions

260 - Domain error happens when the number of decimal points to round to is not in the range 0-12.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:round


The round( Command
ROUND.GIF

Command Summary

Truncates a number to a specified number of decimal places.

Command Syntax

round(value[,#decimals])

Menu Location

Press:

  1. MATH to select the math menu.
  2. RIGHT to select the NUM submenu.
  3. 2 to select round(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

round(value[,#decimals]) returns value rounded to #decimals decimal places. #decimals must be < 10. The default value for #decimals is 9. Also works on complex numbers, lists and matrices.

round(5.45,0)
     5
round(5.65,0)
     6
round(‾5.65,0)
     ‾6
round(π)-π
     4.102e-10
round(π,4)
     3.1416
round({1.5,2.4,3.8},0)
     {2,2,4}
round([[1.8,3.5,120.3][3,‾1,0.2]],0)
     [[2  4   120]
     [3  ‾1  0   ]]

Advanced Uses

Sometimes, round-off error will cause the result of an expression to be slightly off of the correct integer value — for example, a result may be 5.0000000013 instead of 5. If the error is small enough, it will not even be visible if you recall the variable on the home screen. However, this is enough to cause a ERR:DOMAIN error with commands such as sub( and Output(, which require their arguments to be integers.

The easiest way to fix this problem is by wrapping the different arguments in a round( instruction. For example, you may replace Output(X,1,">") with Output(round(X),1,">"). The int( command will not work here because the round-off error may be negative, such as 4.9999999986 instead of 5, in which case the number will be rounded down to 4.

Error Conditions

  • ERR:DOMAIN if the number of places to round to is not an integer 0 through 9.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/round


The *row( Command
TIMESROW.GIF

Command Summary

Multiplies a row by a scalar.

Command Syntax

*row(factor,matrix,row)

Menu Location

Press:

  1. MATRX (on a TI-83) or 2nd MATRX (TI-83+ or higher) to access the matrix menu.
  2. RIGHT to access the MATH submenu.
  3. ALPHA E to select *row(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The *row( command multiplies a row of a matrix by a scalar factor and returns the result. It is an elementary row operation used in Gaussian Elimination.

[[1,2][3,4]]
    [[1 2]
     [3 4]]
*row(10,Ans,1)
    [[10 20]
     [3  4 ]]

Advanced Uses

You can multiply columns instead of rows with the aid of the T (transpose) command.

Error Conditions

  • ERR:INVALID DIM is thrown if the row argument isn't a valid row (is larger than the size of the matrix, or otherwise bad)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/timesrow


The *row+( Command
TIMESROWPLUS.GIF

Command Summary

Adds a multiple of one row of a matrix to another.

Command Syntax

*row+(factor,matrix,row1,row2)

Menu Location

Press:

  1. MATRX (on a TI-83) or 2nd MATRX (TI-83+ or higher) to access the matrix menu.
  2. RIGHT to access the MATH submenu.
  3. ALPHA F to select *row+(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The *row+( adds a multiple of one row to another row and returns the result. It is an elementary row operation used in Gaussian Elimination.

[[1,2][3,4]]
    [[1 2]
     [3 4]]
*row+(10,Ans,1,2)
    [[3  4 ]
     [31 42]]

Advanced Uses

You can add columns instead of rows with the aid of the T (transpose) command.

Error Conditions

  • ERR:INVALID DIM is thrown if one of the row arguments isn't a valid row (larger than the matrix size, or otherwise bad)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/timesrowplus


The row+( Command
ROWPLUS.GIF

Command Summary

Adds one row of a matrix to another.

Command Syntax

row+(matrix,row1,row2)

Menu Location

Press:

  1. MATRX (on a TI-83) or 2nd MATRX (TI-83+ or higher) to access the matrix menu.
  2. RIGHT to access the MATH submenu.
  3. ALPHA D to select row+(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The row+( command adds one row of a matrix to the second, and returns the result. It is an elementary row operation used in Gaussian Elimination.

[[1,2][3,4]]
    [[1 2]
     [3 4]]
row+(Ans,1,2)
    [[1 2]
     [4 6]]

Advanced Uses

You can add columns instead of rows with the aid of the T (transpose) command.

Error Conditions

  • ERR:INVALID DIM is thrown if one of the row arguments isn't a valid row (larger than the matrix size, or otherwise bad)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/rowplus


The rowSwap( Command
ROWSWAP.GIF

Command Summary

Swaps two rows of a matrix.

Command Syntax

rowSwap(matrix,row1,row2)

Menu Location

Press:

  1. MATRX (on a TI-83) or 2nd MATRX (TI-83+ or higher) to access the matrix menu.
  2. RIGHT to access the MATH submenu.
  3. ALPHA C to select rowSwap(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The rowSwap( command swaps two rows of a matrix and returns the result. It is an elementary row operation used in Gaussian Elimination.

[[1,2][3,4]]
    [[1 2]
     [3 4]]
rowSwap(Ans,1,2)
    [[3 4]
     [1 2]]

Advanced Uses

You can swap columns instead of rows with the aid of the T (transpose) command.

Error Conditions

  • ERR:INVALID DIM is thrown if one of the row arguments isn't a valid row (larger than the matrix size, or otherwise bad)

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/rowswap


The RplcPic command

rplcpic.png

Command Summary

Replaces whatever is on the graphscreen with a picture variable at [row][, column]

Command Syntax

RplcPic picVar,[row][, column]

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

This command replaces whatever is on the screen at a specific spot ([row][,column]). If no row or column is specified, the default is the upper left corner (0,0). If the picture is less than the full screen, only the spot at which the picture is placed will be removed. If you do not want anything replaced, use RclPic instead…

Error Conditions

260 - Domain error happens when the [row,column] argument is outside the screen range..

960 - Undefined variable happens when the picture variable specified does not exist..

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:rplcpic


The R►Pr( Command
RTOPR.GIF

Command Summary

R►Pr( calculates the radius component (in polar coordinates) given the Cartesian coordinates.

Command Syntax

R►Pr(x,y)

Menu Location

Press:

  1. 2nd ANGLE to access the angle menu.
  2. 5 to select R►Pr(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

R►Pr( (Rectangular to polar radius) takes the (x,y) (Cartesian) coordinates, and gives the radius coordinate r of the same point in (r,θ) (polar) mode. The identity used for this conversion is r² = x²+y²

R►Pr(3,4)
    5
√(3²+4²)
    5
R►Pr({6,5},{8,12})
    {10 13}

The function works even when the equivalent √(x²+y²) fails due to overflow:

R►Pr(3e99,4e99)
    5e99

Optimization

R►Pr( is the smallest way to implement the distance formula $d=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}$. Just give the values x1-x2 and y1 - y2 as arguments:

:√((5-2)²+(4-0)²)
can be
:R►Pr(5-2,4-0)

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/r-pr


The R►Pθ( Command
RTOPTHETA.GIF

Command Summary

R►Pθ( calculates the angle coordinate (in polar coordinates) given the Cartesian coordinates.

Command Syntax

R►Pθ(x,y)

Menu Location

Press:

  1. 2nd ANGLE to access the angle menu.
  2. 6 to select R►Pθ(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

R►Pθ( (Rectangular to polar θ) takes the (x,y) (Cartesian) coordinate, and returns the angle that the ray from (0,0) to (x,y) makes with the positive x-axis. This is the θ-coordinate of the same point in (r,θ) (polar) mode. The identity used for this conversion is tan(θ)=y/x, with the correct inverse being chosen depending on the quadrant that the point is in. The range of the angle returned is -π<θ≤π. R►Pθ( can also be used on lists.

R►Pθ( is equivalent to the atan2() instruction seen in C/++ and FORTRAN.

R►Pθ(3,4)
    .927295218
tanֿ¹(4/3)
    .927295218
R►Pθ(0,{1,-1})
    {1.570796327, -1.57096327}

R►Pθ( is affected by Degree and Radian mode in its output, which is an angle measured in degrees or radians respectively.

Advanced Uses

If you want the result to always be a radian angle, regardless of mode settings, you can divide the result by 1r:

R►Pθ(x,y)/1^^r

If you want the result to always be a degree angle, regardless of mode settings, you can divide the result by 1°:

R►Pθ(x,y)/1°

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/r-ptheta


The rref( Command
RREF.GIF

Command Summary

Puts a matrix into reduced row-echelon form.

Command Syntax

rref(matrix)

Menu Location

Press:

  1. MATRX (on the TI-83) or 2nd MATRX (TI-83+ or higher) to access the matrix menu.
  2. RIGHT to access the math menu.
  3. ALPHA B to select rref(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

Given a matrix with at least as many columns as rows, the rref( command puts a matrix into reduced row-echelon form using Gaussian elimination.

This means that as many columns of the result as possible will contain a pivot entry of 1, with all entries in the same column, or to the left of the pivot, being 0.

[[1,2,5,0][2,2,1,2][3,4,6,2]]
    [[1 2 5 0]
     [2 2 1 2]
     [3 4 7 3]]
rref(Ans)
    [[1 0 0 6   ]
     [0 1 0 -5.5]
     [0 0 1 1   ]]

Advanced Uses

The rref( command can be used to solve a system of linear equations. First, take each equation, in the standard form of $a_1x_1+\dots + a_nx_n = b$, and put the coefficients into a row of the matrix.

Then, use rref( on the matrix. There are three possibilities now:

  • If the system is solvable, the left part of the result will look like the identity matrix. Then, the final column of the matrix will contain the values of the variables.
  • If the system is inconsistent, and has no solution, then it will end with rows that are all 0 except for the last entry.
  • If the system has infinitely many solutions, it will end with rows that are all 0, including the last entry.

This process can be done by a program fairly easily. However, unless you're certain that the system will always have a unique solution, you should check that the result is in the correct form, before taking the values in the last column as your solution. The Matr►list( command can be used to store this column to a list.

Error Conditions

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/rref


The Sci Command
SCI.GIF

Command Summary

Puts the calculator in scientific notation mode.

Command Syntax

Sci

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. Use arrows and ENTER to select Sci.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Sci command puts the calculator in scientific notation mode, so that all results are displayed in scientific notation: as a (possibly fractional) number between 1 and 10 (not including 10) multiplied by a power of 10.

Sci
        Done
1000
        1e3
{1,2,3}
        {1e0 2e0 3e0}

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/sci


The sec() Command

sec.png

Command Summary

Takes the secant of a number (usually, an angle).

Command Syntax

sec(angle)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press A to enter the Trig submenu.
  • Press 5 to select sec(.

Calculator Compatibility

This command requires a calculator with AMS version 2.07 or higher (it will also work on any TI-89 Titanium or Voyage 200 calculator)

Token Size

1 byte

The sec() command returns the secant (the reciprocal of the cosine) of an angle measure. Naturally, the result depends on the angle mode the calculator is in: radian, degree, or (in AMS version 3.10) gradian. You can also use one of the r, °, G marks to specify an angle mode.

The sec() command, along with 11 other trig and hyperbolic functions, was added with AMS version 2.07. It can be easily replaced on earlier versions with 1/cos(x), which is what it simplifies to anyway.

For many common angles, sec() can compute an exact result. Other angles, the calculator will leave alone unless it's in approximate mode (or unless you make it approximate), and then it will give a decimal approximation. As long as the calculator is in radian mode, sec() can be used with complex numbers as well.

:sec(60°)
           2
:sec(x)
          1/cos(x)
:sec(π/2)
          undef

If sec() is applied to a list, it will take the secant of every element in the list. However, it can't be applied to matrices the way cos() can (this is probably an oversight; all the trig and hyperbolic functions that were present in all AMS versions work with matrices, but the ones added in version 2.07 do not).

Error Conditions

260 - Domain error happens when taking sec() of a complex number in degree or gradian mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:sec


The sech() Command

sech.png

Command Summary

Takes the hyperbolic secant of a number.

Command Syntax

sech(value)

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press C to enter the Hyperbolic submenu.
  • Press 5 to select sech(.

Calculator Compatibility

This command requires a calculator with AMS version 2.07 or higher (it will also work on any TI-89 Titanium or Voyage 200 calculator)

Token Size

1 byte

The sech() command returns the hyperbolic secant of a number. Along with 11 other trig and hyperbolic functions, it was added in AMS version 2.07; on earlier versions, sech(x) can be replaced by 1/cosh(x).

As long as the calculator is in radian mode, sech() can be used with complex numbers according to the rule that sech(ix)=sec(x) and sec(ix)=sech(x). This rule only works in radian mode, and sech() of a complex number will return a domain error when working in degrees or gradians.

Occasionally, sech() can compute an exact result; most of the time, the calculator will leave an expression with sech() alone unless it's in approximate mode (or you force an approximation). When sech() is used with symbolic expressions, the calculator can go back and forth between the sech() expression and its exponential equivalent.

:sech(0)
           1
:expand(sech(x))
          2*e^x/((e^x)^2+1)
:comDenom(2*e^x/((e^x)^2+1))
          1/cosh(x)

If sech() is applied to a list, it will take the hyperbolic secant of every element in the list. However, it can't be applied to matrices the way cosh() can (this is probably an oversight; all the trig and hyperbolic functions that were present in all AMS versions work with matrices, but the ones added in version 2.07 do not).

Formulas

The definition of hyperbolic secant is, by analogy with sec(), the reciprocal of cosh():

(1)
\begin{align} \operatorname{sech}{x}=\frac{1}{\cosh{x}} = \frac{2}{e^x+e^{-x}} \end{align}

Error Conditions

260 - Domain error happens when taking sech() of a complex number in degree or gradian mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:sech


The Select( Command
SELECT.GIF

Command Summary

Allows the user to select a subinterval of any enabled Scatter or xyLine plots.

Command Syntax

Select(x-list name, y-list name)

Menu Location

Press:

  1. 2nd LIST to access the list menu.
  2. RIGHT to access the OPS submenu.
  3. 8 to select Select(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

When Select( is called, if it has any Scatter or xyLine plots to work with, it displays the graph screen and allows the user to pick a left bound and then a right bound on one of the plots (the left and right keys move from point to point, while the up and down keys switch plots). Then, it stores all the points between those bounds to x-list name and y-list name. Finally, it sets the chosen plot to use x-list name and y-list name as its X and Y lists.

Optimization

It isn't necessary to add the ∟ symbol before list names:

:Select(∟X,∟Y)
can be
:Select(X,Y)

Error Conditions

  • ERR:INVALID is thrown if there are no enabled Scatter or xyLine plots for the command to work with.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/select


The Send( Command
SEND.GIF

Command Summary

Sends data or a variable to a connected CBL device.

Command Syntax

Send(variable)

Menu Location

While editing a program, press:

  1. PRGM to access the program menu.
  2. RIGHT to access the I/O submenu.
  3. ALPHA B to select Send(.

Calculator Compatibility

TI-83/84/+/SE/CSE/CE(5.1.5+)

Token Size

1 byte

The Send( command is used for sending data to a CBL (Calculator Based Laboratory) device (or another compatible device) via a link cable. With some exceptions, Send('s argument must be a variable: a real number, list, matrix, string, equation, picture, or GDB. An expression or a number will not work — Send(5) or Send([A][B]) is invalid.

The exceptions are list or matrix elements (that is, you can do Send([A](1,1)) or Send(L1(2)) without an error) and non-variable lists typed out with { } brackets and commas.

Norland Robot

You can use Send( with a Get( for a Norland calculator robot. The format called CLR format. C stands for command number, L stands for left axle, and R stands for right axle. If the command number is 1, it makes the robot moves in a direction for the time specified later in the command. If it is 2, the robot moves until the bumper hits a wall. If it is 3, it moves for a specified amount of time and stops when the robot when the bumper hits a wall. For example, send({122,100}) will make the robot move forward for 100 centiseconds, send({222}) makes it go forward until the bumper hits the wall, and send({322,100}) makes the robot move forward for 100 centiseconds and stops it when the bumper is pressed. The last two axle control numbers are like this:
0=backwards
1=stop
2=forwards

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/send


The seq( Command
SEQ-LIST.GIF

Command Summary

Creates a list by evaluating a formula with one variable taking on a range of values, optionally skipping by a specified step.

Command Syntax

seq(formula, variable, start-value, end-value [, step])

Menu Location

While editing a program, press:

  1. 2nd LIST to enter the LIST menu
  2. RIGHT to enter the OPS submenu
  3. 5 to choose seq(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE/CSE/CE

Token Size

1 byte

The seq( command is very powerful, as it is (almost) the only command that can create a whole list as output. This means that you will need make use of it almost every time that you use lists. The seq( command creates a list by evaluating a formula with one variable taking on a range of several values.

It is similar in this to the For( command, but unlike For(, instead of running a block of commands, it only evaluates a formula. Like the For( command, there is an optional "step" that you can use to get every 3rd, every 5th, etc. value in the range.

Some sample uses of the command:

:seq(I,I,3,7
  • evaluates the expression 'I' with I taking on the values 3..7
  • returns {3,4,5,6,7}
:seq(AX²,X,1,7
  • evaluates the expression AX² with X taking on the values 1..7
  • returns {A,4A,9A,16A,25A,36A,49A}, depending on the value of A
:seq(Y1(T),T,1,9,2
  • evaluates the expression Y₁(T) with T taking on every 2nd value 1..9
  • returns {Y₁(1),Y₁(3),Y₁(5),Y₁(7),Y₁(9)} depending on Y₁

Note: the value of the variable used in the expression does not change. If X has some value stored to it, and you do a seq( command using X, X will still hold that original value. However, if X was undefined before the command, after the command, it will be defined and have a value of 0.

Advanced Uses

The step argument supplied can be negative. If it is, and if the starting value is greater than the ending value, then the sequence will "go backward", evaluating the expression in the opposite order. For example:

:seq(I,I,1,7
    {1,2,3,4,5,6,7}
:seq(I,I,7,1,-1
    {7,6,5,4,3,2,1}

You can use seq( to get a "sublist", that is, to get a list that is only a section of another list. This is pretty much the only effective way to extract a sublist. For example, to get the 2nd through 10th elements of L₁, do the following:

:seq(L1(I),I,2,10

While using seq(, the calculator can still interpret keypresses and store them to getKey. One possible way you can use this feature is to make a password function that asks the user to enter in the correct password before time expires.

Optimizations

It's faster to do an operation on an entire list, than to do the same operation inside a seq( command. For example, take the following:

:seq(Y1(T),T,1,9
can be
:Y1(seq(T,T,1,9

However, not all commands that work for numbers will work for lists. A notable example is getting an element from a list: L₁({1,2,3 will not return the first, second, and third elements of L₁, so you will have to put the L₁ inside the seq( command.

For this same reason, you shouldn't use a seq( command when you're really performing an operation on each element of a list. For example, if L₁ has 10 elements:

:seq(L1(I)²,I,1,dim(L1
can be
:L1²

When generating a list of values incremented by a number i from i to a number N, seq( is not recommended as the amount of overhead on the command considerably slows the generation of the list.
In cases where such a list is to be generated, it is beneficial to generate a list of a specific length, fill that list with the incrementer, and cumulatively sum each value in the list. For example, if a list of all the numbers between 1 and 500 were desired:

:500→dim(L1
:Fill(1,L1
:cumSum(L1→L1

This operation can be sped up even more using binomcdf( or binompdf(.

A seq( command can replace a For( command, if all you're doing inside the For( command is storing to an element of a list. This will improve on both speed and size of your program. For example:

:For(I,1,10
:I²→L1(I
:End
can be
:seq(I²,I,1,10→L1

The seq( command itself can often be replaced with an unusual use of the binomcdf( or binompdf( commands, improving speed and sometimes size as well. However, this optimization is fairly advanced; read the pages for those commands to learn about it.

Error Conditions

  • ERR:ILLEGAL NEST is thrown if you try to use seq( inside of another seq( command.
  • ERR:DATA TYPE occurs when any of the inputted arguments are imaginary or complex.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/seq-list


The seq() Command

seq.png

Command Summary

Creates a list by evaluating a formula over a range of values.

Command Syntax

seq(formula,variable,start,end[,step-size]

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 3 to enter the List submenu.
  • Press 1 to select seq(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The seq() command creates a list of terms of a sequence: seq(formula,variable,start,end) evaluates formula for every value of variable from start to end. Optionally, a fifth argument, step-size, is included: this increases the value of variable by step-size for each element, instead of 1.

seq() is similar to a For..EndFor loop, but instead of repeating a block of commands every time, it only evaluates a formula.

:seq(f(x),x,1,5)
           {f(1)  f(2)  f(3)  f(4)  f(5)}
:seq(x,x,3,9,2)
           {3  5  7  9}
:seq(x^2,x,5,1,-1)
           {25  16  9  4  1}

The variable used in seq(), x in the examples, is not actually modified.

Advanced Uses

Because a matrix is just a list of lists, you can use seq() to create matrices as well as lists. The simplest way to do it is to make the formula a list:

:seq({x,2x,3x},x,1,4)
           [1  2  3 ]
           [2  4  6 ]
           [3  6  9 ]
           [4  8  12]

You can also create a matrix by nesting a seq() command inside another seq() command:
:seq(seq(row+col,col,1,4),row,1,3)
           [2  3  4  5]
           [3  4  5  6]
           [4  5  6  7]

Optimization

If all you need to do in a loop is create a list, it's probably better to use seq() than For..EndFor.


You can often use newList() instead of seq() to create an expression that gets evaluated much faster (see List Optimization for details).

Error Conditions

For the non-generic errors that might occur when using this command (that is, syntax-type errors shouldn't be included). In a format similar to the following:

260 - Domain error happens when the step-size argument is 0.

510 - Invalid list or matrix happens when the formula of seq() is a matrix, or a list that varies in size.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:seq


The Seq Command
SEQ-MODE.GIF

Command Summary

Enables sequence graphing mode.

Command Syntax

Seq

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. Use arrows to select Seq.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Seq command enables sequence graphing mode.

Sequential mode is used for graphing sequences, which can be thought of as functions from the positive (or non-negative) integers. The TI-83 calculators let n be the independent variable in this situation, and the three sequences, instead of using subscripts, use the letters u, v, and w.

One of the main advantages of sequential mode is that it allows recursive definitions: u(n) can be defined in terms of u(n-1) and u(n-2). For recursive definitions to work, an initial case must be defined: this is done using the variables u(nMin), v(nMin), and w(nMin). The constant nMin is the initial case, for which the calculator will use a specific value rather than the formula.

For example, say a bunny population starts out at 100 and doubles each year. We can describe this situation using the recursive definition u(n)=2u(n-1) (this just says that the nth year population is twice the population of the previous year); then we set u(nMin)=100. Note that without u(nMin), the equation would be meaningless - without the initial population, we have no way to calculate any other population.

When you're using more than one previous value — both u(n-1) and u(n-2)) — you need more than one initial value, and then u(nMin) becomes a list.

Advanced Uses

Sequence graphing mode has several submodes that can be selected from the 2nd FORMAT screen. They are Time, Web, uvAxes, uwAxes, and vwAxes. Sequences are still defined in the same way, but these modes control the way that they're graphed.

The window variables that apply to sequence mode are:

  • nMin — Determines the minimum n-value calculated for equations.
  • nMax — Determines the maximum n-value calculated for equations.
  • PlotStart — Determines the first value of n that is actually graphed.
  • PlotStep — Determines the difference between consecutive graphed values of n.
  • Xmin — Determines the minimum X-value shown on the screen.
  • Xmax — Determines the maximum X-value shown on the screen.
  • Xscl — Determines the horizontal space between marks on the X-axis in AxesOn mode or dots in GridOn mode.
  • Ymin — Determines the minimum Y-value shown on the screen.
  • Ymax — Determines the maximum Y-value shown on the screen.
  • Yscl — Determines the vertical space between marks on the Y-axis in AxesOn mode or dots in GridOn mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/seq-mode


The Sequential Command
SEQUENTIAL.GIF

Command Summary

Puts the calculator into sequential graphing mode.

Command Syntax

Sequential

Menu Location

While editing a program, press:

  1. MODE to access the mode menu.
  2. Use arrows and ENTER to select Sequential.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

Puts the calculator into sequential graphing mode (the default). When multiple equations are enabled at the same time, sequential graphing mode means that they will be graphed one after the other (as opposed to Simul mode, in which they will be graphed simultaneously)

If you use a list in an equation, as with Y1={1,2,3}X, this will graph several equations that will always graph separately, regardless of this setting, which only affects multiple functions in different equation variables.

Make sure not to confuse this with Seq mode, which is referred to in this guide as sequence graphing mode.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/sequential


The setDate( Command
SETDATE.PNG

Command Summary

Sets the date of the clock on the TI-84+/SE.

Command Syntax

setDate(year,month,day)

Menu Location

This command can only be found in the catalog. Press:

  1. 2nd CATALOG to enter the command catalog
  2. s to skip to commands starting with S
  3. Scroll down to setDate( and select it

Calculator Compatibility

TI-84+/SE

Token Size

2 bytes

The setDate( command sets the date of the clock on the TI-84+/SE calculators. It takes three arguments: the year, the month, and the day. All three of these must be integers; in particular, year must be four digits, and month and day can be one or two digits. They represent the associated value that goes with a respective date. For example, this would set the date to January 1, 2008:

:setDate(2008,1,1

Once you have set the date, you can display it in three different formats on the mode screen using the setDtFmt( command: Month/Day/Year, Day/Month/Year, or Year/Month/Day. Of course, the date will only show up if the clock is on; if you need to turn the clock on, use the ClockOn command or select 'TURN CLOCK ON' , displayed in place of the clock on the mode screen.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/setdate


The SetDate command

setdate.png

Command Syntax

setDate(year, month, day)

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command requires a calculator with AMS version 2.07 or higher (it will also work on any TI-89 Titanium or Voyage 200 calculator)

This command sets the calculator's date to whatever is specified in the command. The year must fall in the range 1997 to 2132 for this command to work.

:setDate(2001, 10, 31)
:      {2001, 11, 1}

The above example has set the calculator's date to October 31st, 2001, and the date it was set at originally was November 1st, 2001.

Error Conditions

40 - Domain error happens when the year is outside of the range of 1997 to 2132, or the month is above or below 0 to 12, or the date is above or below 0 to 31.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:setdate


The setDtFmt( Command
SETDTFMT.PNG

Command Summary

Sets the date format of the clock on the TI-84+/SE.

Command Syntax

setDtFmt(value)

Menu Location

This command can only be found in the catalog. Press:

  1. 2nd CATALOG to enter the command catalog
  2. s to skip to commands starting with S
  3. Scroll down to setDtFmt( and select it

Calculator Compatibility

TI-84+/SE

Token Size

2 bytes

The setDtFmt( command sets the date format of the clock on the TI-84+/SE calculators when displaying the date on the mode screen. There are three different formats available, and you simply use the respective value (can be either a literal number or a variable) to display the desired one: 1 (M/D/Y), 2 (D/M/Y), or 3 (Y/M/D). For example, this would set the date format to Month/Day/Year:

:setDtFmt(1

In order for the date format to work, you need to set the date using either the setDate( command, or by going into the set clock menu (accessible by pressing ENTER on the 'SET CLOCK' message that is displayed at the bottom of the mode screen). Of course, the date will only show up if the clock is on; if you need to turn the clock on, use the ClockOn command, or scroll down to the 'TURN CLOCK ON' message that is displayed in place of the clock on the mode screen and press ENTER twice.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/setdtfmt


The setDtFmt() Command

setdtfmt.png

Command Summary

Sets the default date format.

Command Syntax

setDtFmt(format-number)

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command requires a calculator with AMS version 2.07 or higher (it will also work on any TI-89 Titanium or Voyage 200 calculator)

Token Size

3 bytes

The setDtFmt() sets the default format for dates: this format is used in the top right corner of the Apps Desktop, and also as the format for the output of getDtStr() (when it's used without a parameter to override this setting).

The eight possible formats each have a number associated to them, which is the number you should pass to setDtFmt(). It will return the number of the previous setting, which is convenient if you want to restore it later.

The eight formats are as follows (dd, mm, and yy are the date, month, and year respectively, in two digits)

Format Number Date Format
1 "mm/dd/yy"
2 "dd/mm/yy"
3 "mm.dd.yy"
4 "dd.mm.yy"
5 "yy.mm.dd"
6 "mm-dd-yy"
7 "dd-mm-yy"
8 "yy-mm-dd"

Typically, you'd only use this command in a program if you needed to use getDtStr() many times with the same format. In that case, save the return value of setDtFmt(), and use it to restore the date format at the end of the program.

Error Conditions

40 - Argument error happens when the format number is not an integer in the range 1-8.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:setdtfmt


The setGraph() Command

setgraph.png

Command Summary

Changes any of the graph settings.

Command Syntax

setGraph(setting,value)

Menu Location

This command can't be found in any menu besides the command catalog.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The setGraph() command is an analog of the setMode() command, except that it's used specifically to change graph settings. setGraph(setting,value) will change setting to value, and return the old value of setting. Both settings and values are identified by strings (not case-sensitive, but very spelling-sensitive), which are listed on the Mode Settings page.

:setGraph("Coordinates","OFF")
           "RECT"
:setGraph("Axes","OFF")
           "ON"

Unlike setMode(), you can't change more than one setting at a time; there isn't a getGraph() function either, although you could use setGraph() to determine the mode setting if you really needed to.

Advanced Uses

As an alternative to the long and hard-to-remember strings, you can also identify the settings and values of setGraph() with short and still hard-to-remember numbers (or rather, string versions of numbers). The equivalents are also listed on the Mode Settings page. For instance, "Coordinates" can be replaced with "1", and "IMPLICIT PLOT" with "5". If you use these codes as arguments to setGraph(), it will return such a code as well.

There are two advantages to this. First of all, writing the numbers is shorter, so it saves some space in the program. Second, it ensures that if, say, a French speaker is using your program with the language set to French, it will still work (normally, strings like "Coordinates" depend on the language setting).


Use the output of setGraph() to restore settings to what they were previously:

:setGraph("Axes","OFF")→oldaxes
...
:setGraph("Axes",oldaxes)

Error Conditions

130 - Argument must be a string happens when the data type of arguments is incorrect.

260 - Domain error happens when the string used to identify a setting is incorrect or misspelled.

430 - Invalid for the current mode settings happens when a setting depends on other settings that are incorrect (e.g. setting "XR Style" when the calculator is not in 3D graphing mode).

450 - Invalid in a function or current expression happens when setGraph() is used in a function.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:setgraph


The setMode() Command

setmode.png

Command Summary

Changes one or more mode settings.

Command Syntax

  • setMode(setting,value)
  • setMode({set1,val1,…})

Menu Location

Starting in the program editor:

  • Press F6 to enter the Mode menu.
  • Select the desired setting to enter its submenu.
  • Select the desired value to paste setMode("setting", "value")

Calculator Compatibility

This command works on all calculators.

Token Size

3 bytes

The setMode() command is used, mainly by programmers, to change mode settings (outside a program, of course, you can just select the settings in the MODE menu). When a setting is changed, it returns the old value of the setting. There are two ways to use the command:

  • setMode(setting,value) will change setting to value, and return the old value of setting.
  • setMode({set1,val1,…}) will change set1 to val1, set2 to val2, and so on, for any number of settings, and return a list in the same format of settings and their old values.

The first format is used to change only one setting, and the second to change several settings.

Both settings and values are identified by strings (not case-sensitive). All the strings involved are given in the Table of Mode Settings.

An example of setMode():

setMode("Angle","DEGREE")
           "RADIAN"
setMode({"Angle","RADIAN","Split Screen","FULL"})
           {"Split Screen" "FULL" "Angle" "DEGREE"}

Advanced Uses

Unfortunately, the strings depend on language localization. For compatibility with other languages, there is an alternate identification for the settings and values: you can use a string containing a number identifying the setting or value (see the Table of Mode Settings). This is also shorter.

As an example, the numerical version of the sample code above would be:

setMode("3","2")
           "1"
setMode({"3","1",8","1"})
           {"8" "1" "3" "2"}

Use the output of the list version of setMode() to restore settings to what they were previously:

:setMode({"Angle","RADIAN"})→oldmode
...
:setMode(oldmode)

This works with the numerical or the verbose versions of the command; the output of the command will be in the same format as the input.

Error Conditions

130 - Argument must be a string happens when the data type of arguments is incorrect.

260 - Domain error happens when the string used to identify a setting is incorrect or misspelled.

430 - Invalid for the current mode settings happens when a setting depends on other settings that are incorrect (e.g. setting "Split 2 App" if "Split Screen" is "FULL").

450 - Invalid in a function or current expression happens when setMode() is used in a function.

Related Commands

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:setmode


The setTime( Command
SETTIME.PNG

Command Summary

Sets the time of the clock on the TI-84+/SE.

Command Syntax

setTime(hour,minute,second)

Menu Location

This command can only be found in the catalog. Press:

  1. 2nd CATALOG to enter the command catalog
  2. s to skip to commands starting with S
  3. Scroll down to setTime( and select it

Calculator Compatibility

TI-84+/SE

Token Size

2 bytes

The setTime( command sets the time of the clock on the TI-84+/SE calculators. It takes three arguments: the hour, the minute, and the second. The hour must be in 24 hour format — where 13 is equal to 1 P.M. — and the minute and second need to be a valid number within the appropriate range (1-60). For example, this would set the time to 12:30:30:

:setTime(12,30,30

Once you have set the time, you can display it in two different formats on the mode screen using the setTmFmt( command: 12 (12 hour) or 24 (24 hour). Of course, the time will only show up if the clock is on; if you need to turn the clock on, use the ClockOn command, or scroll down to the 'TURN CLOCK ON' message that is displayed in place of the clock on the mode screen and press ENTER twice.

Related Commands

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/settime


The setTime() Command

settime.png

Command Summary

Sets the current time on the calculator's clock, returning the previous time