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


Command Index

Ops | A | B | C | D | E | F | G | I | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z

Ops

+, -, ·, /, ^, ^ֿ¹, ²
.+, .-, , ./, .^
=, , <, , >,
(insert implies arrow here), (insert iff arrow here)
10^(), E, !, %, ,
d(), (insert integral symbol here), Π(), Σ(), ΣInt(), ΣPrn()
&, #, ', _, |, ©
(insert angle symbol here), º, ', ", g, r
:=, ,
0b, 0h

A

abs()
amortTbl()
and
angle()
ANOVA
ANOVA2way
Ans
approx()
▶approxFraction()
approxRational()
arccos()
arccosh()
arccot()
arccoth()
arccsc()
arccsch()
arcLen()
arcsec()
arcsech()
arcsin()
arcsinh()
arctan()
arctanh()
augment()
avgRC()

B

bal()
▶Base2
▶Base10
▶Base16
binomCdf()
binomPdf()

C

ceiling()
centralDiff()
cFactor()
char()
charPoly()
x²2way()
x²Cdf()
x²GOF
x²Pdf()
ClearAZ
ClrErr
colAugment()
colDim()
colNorm()
comDenom()
completeSquare()
conj()
constructMat()
CopyVar
corrMat()
▶cos
cos()
cosֿ¹()
cosh()
coshֿ¹()
cot()
cotֿ¹()
coth()
cothֿ¹()
count()
countif()
cPolyRoots()
crossP()
csc()
cscֿ¹()
csch()
cschֿ¹()
cSolve()
CubicReg
cumulativeSum()
Cycle
▶Cylind
cZeros()

D

dbd()
▶DD
▶Decimal
Define
Define LibPriv
Define LibPub
deltaList()
deltaTmpCnv()
DelVar
delVoid()
derivative()
deSolve()
det()
diag()
dim()
Disp
▶DMS
domain()
dominantTerm()
dotP()

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


Command Index (Black & White)

Ops | # | A | B | C | D | E | F | G | H | I | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z

This page lists all of the commands for the TI-83/84/SE/+ models. If you have a newer TI-84 Plus C Silver Edition or TI-84 Plus CE with a color display, please visit the Color Command Index.

To access more information about the command, click on the command to go to the dedicated page for that command. To view the commands divided into sections, go to the Command Overview. To view most of the commands as they would on the calculator itself through the menus, go to the Command Menu Map.

Some commands have a superscript next to them that indicates compatibility:

  • 83+ indicates that the command requires a TI-83+, TI-83+SE, TI-84+, TI-84+SE, or TI-84+CSE calculator.
  • 84+ indicates that the command requires a TI-84+,TI-84+SE, or TI-84+CSE calculator.
  • 84+2.30 indicates that the command requires a TI-84+, TI-84+SE, or TI-84+CSE calculator with OS 2.30 or higher.
  • 84+2.53MP indicates that the command requires a TI-84+, TI-84+SE, or TI-84+CSE calculator with OS 2.53MP or higher.

See Compatibility for a chart of only the commands that require certain calculators or operating systems.

Ops

#

A

B

C

D

E

F

G

H

I

L

M

N

O

P

Q

R

S

T

U

V

W

X

Z

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


Command Index (Color)

Ops | # | A | B | C | D | E | F | G | H | I | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z

This page lists all of the commands for the TI-84 Plus C Silver Edition and the TI-84 Plus CE. If you have an older TI-83/84+ with a monochrome display, please visit the Monochrome Command Index.

To access more information about the command, click on the command to go to the dedicated page for that command. To view the commands divided into sections, go to the Command Overview. To view most of the commands as they would on the calculator itself through the menus, go to the Command Menu Map.

Some commands have a superscript next to them that indicates compatibility:

  • CE indicates that the command requires a TI-84 Plus CE or a specific OS version

See Compatibility for a chart of only the commands that require certain calculators or operating systems.

Ops

#

A

B

C

D

E

F

G

H

I

L

M

N

O

P

Q

R

S

T

U

V

W

X

Z

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


Overview of Commands

The TI-Basic programming language features a wide range of commands for all kinds of things, including output, user input, manipulating variables, linking calculators, and especially math — don't forget a calculator is primarily designed for doing math. In total, there are almost 400 commands on the TI-83+ calculators, and the TI-84+/SE calculators have an additional 22 commands (because of the new time and date commands and the new math commands added in OS 2.30).

Because sorting through all of these commands is a rather daunting task, especially when trying to figure out which one is appropriate for accomplishing a desired task, we have chosen to present them in three different formats:

  • Alphabetical Index — A listing of the commands sorted in alphabetical order.
  • Menu Map — A listing of the commands sorted by where they appear in their different menus on the calculator.
  • Category — A listing of the related commands grouped together based on their common function and purpose.

There are eleven different command categories that we have come up with:

We tried to do our best to come up with these categories because we believe they reflect the natural divisions of the commands, although some of the commands have functionality that overlaps more than one category. In this case, we decided to simply go with the primary use of the command.

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


Summationsigma

This command will open up a template that allows you to evaluate an expression in sigma notation.
This command is accessible by pressing ALPHA then WINDOW then 2.
This command is especially useful for statistics and algebra.
It is also available in the programming mode. You can access it either through the catalog or the same way specified above.
The syntax for this command is

Σ(Expression,Variable,Starting number,Ending number)

An example would be to determine the sum of 2*X for X going from 1 to 10.
It would look like this:
Σ(2X,X,1,10

The result would be
110

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


The ^ Command
POWER.GIF

Command Summary

Raises a number to a power.

Command Syntax

x^y

Menu Location

Press [^]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ^ operator is used to raise a number to a power. It can be used with numbers, expressions, and lists. It can be used for taking nonnegative integer powers of square matrices (up to the 255th power only, however), but not for negative powers (use ֿ¹ instead) or matrix exponentials (which the TI-83+ cannot do).

In general, x^y returns the same results as e^(y*ln(x)). For expressions of the form x^(p/q), where p and q are integers and q is an odd number, the principal branch is returned if x is complex, but the real branch is returned if x is a negative real number.

(-1)^(1/3)
        -1
(-1+0i)^(1/3)
        .5+.8660254038i

Optimization

When raising 10 or e to a power, use the 10^( and e^( commands instead. Similarly, use the ², ³, or ֿ¹ commands for raising a number to the 2, 3, or -1 power.

Error Conditions

  • ERR:DOMAIN is thrown when calculating 0^0, or raising 0 to a negative power.
  • ERR:NONREAL ANS is thrown in Real mode if the result is complex (and the operands are real)

Related Commands

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


The ^ Command

power.png

Command Summary

Raises a number to a power.

Command Syntax

base ^ exponent

Menu Location

Press the [^] key to paste ^.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ^ operator is used to raise a number (the base) to a power (the exponent) — x^y is "pretty-printed" as xy. When the exponent is a positive integer, this is equivalent to multiplying the base by itself that many times.

When the base is a real number, the result will always be a real number if possible: for example (-1)^(1/3) will return -1. Some powers will return a complex number because there is no real number answer (or give an error, if the calculator is in real number mode). When the base is a complex number, the result will be the principal branch.

For lists, the ^ operator works componentwise — x^{a,b,c,…} will return {x^a,x^b,x^c,…}, {x,y,z,…}^a will return {x^a,y^a,z^a,…}, and two lists of the same length will be matched up element by element.

:2^4
           16
:(-1)^(1/2)
           i
:0^0
           undef

Typing [2nd] [LN] or [♦] [LN] also pastes e^( — this is not a separate command (unlike the TI-83 series), and just uses the ^ operator to do its work. It is, however, the simplest way to type the constant e.

A minor quirk of the ^ operator is that if it's present multiple times in one expression, it is evaluated right to left (unlike most commands, which are evaluated left to right). For example, x^y^z will be interpreted as x^(y^z) rather than (x^y)^z. The reason this is done is that (x^y)^z can easily be rewritten as x^(y*z), so there's no need for two powers. x^(y^z) can't be rewritten that way. Therefore, it's much more meaningful to interpret x^y^z as x^(y^z).

Advanced Uses

The ^ operator can be used as an alternative to an "xth root" operator, which the 68k calculators don't have. If you want to take the Nth root of a number, raise it to the 1/N-th power instead.


The ^ operator is also useful for square matrices. Raising a square matrix to an integer power between -32768 and 32767 just multiples the matrix by itself, taking the inverse first for negative matrices. A matrix to the 0th power is the identity.

For raising a matrix to a fractional power, or raising a number to a matrix power, a different definition is used: see Matrices and Their Commands. This definition is in fact compatible with the repeated-multiplication method, except that it is far more general.

None of these situations are equivalent to applying ^ to every element of a matrix. For that, see the .^ command.

Error Conditions

230 - Dimension happens when non-square matrices are used with ^.

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 ^ 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

  • * (multiply)
  • / (divide)

See Also

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


The ×√ Command
XROOT.GIF

Command Summary

Takes the xth root of an input.

Command Syntax

A xB

Menu Location

While editing a program, press:

  1. MATH to open the math menu
  2. 5 or use the arrow keys to select

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

This command takes the xth root of a number. If used on a list, it will return a list with the xth root of each element. Also valid are the forms list×x and list1×list2.

:2×√4
        2
:5×√2
        1.148698355

:3×√{1,‾8,27}
        {1 ‾2 3}

:{3,2}×√{8,9}
        {2 3}

Real mode:
:4×√‾1
    <returns error>

a+bi mode:
:4×√‾1
        .7071067812+.7071067812i

See the notes on the ^ command for an explanation on how ×√ behaves depending on whether its input is real or complex.

Optimization

If you want to take the second or third root of a number, use √( or ³√( instead.

:2×√X
can be
:√(X

Error Conditions

  • ERR:NONREAL ANS if you try to take an even root of a negative number or list element in Real mode.

Related Commands

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


The ≠ Command
NOTEQUAL.PNG

Command Summary

Returns true if value1 is not equal to value2.

Command Syntax

value1value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. 2 to select ≠, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ≠ (not equal) operator takes two numbers, variables, or expressions, and tests to see if they are not equal to each other. It will return 1 if they are not, and 0 if they are. When determining the order of operations, ≠ will be executed after the math operators, but it will be executed before the logical operators and in the order that it appears from left to right with the other relational operators.

1≠0
           1
0→X
           0
3→Y
           3
X≠Y
           1

Advanced Uses

Just like the other relational operators, ≠ can take real numbers and lists for variables. In order to compare the lists, however, both must have the same dimensions; if they don't, the calculator will throw a ERR:DIM MISMATCH error. When comparing a real number to a list, the calculator will actually compare the number against each element in the list and return a list of 1s and 0s accordingly.

:{2,4,6,8}≠{1,3,5,7
           {1 1 1 1}
:5≠{1,2,3,4,5
           {1 1 1 1 0}

Besides real numbers and lists, ≠ also allows you compare strings, matrices, and complex numbers. However, the variables must be of the same type, otherwise the calculator will throw a ERR:DATA TYPE error; and just like with lists, both matrices must have the same dimensions, otherwise you will get a ERR:DIM MISMATCH error.

:[[1,2,3]]≠[[1,2,3
           0
:"HELLO"≠"WORLD
           1
:(3+4i)≠(5-2i)    (the parentheses are added for clarity)
           1

Optimization

Don't compare a variable's value to zero in a conditional expression, because the calculator treats nonzero values as true and zero as false. Instead, just write the variable by itself:

:If C≠0
can be
:If C

Error Conditions

  • ERR:DATA TYPE is thrown if you try to compare two different kinds of variables, such as a string and number or a list and matrix.
  • ERR:DIM MISMATCH is thrown if you try to compare two lists or matrices that have different dimensions.

Related Commands

  • = (equal)
  • > (greater than)
  • (greater than equal)
  • < (less than)
  • (less than equal)

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


The ≠ Command

notequal.png

Command Summary

Tests if two values are different.

Command Syntax

value1value 2

Menu Location

Press [♦][=] key to enter ≠.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ≠ operator compares two values, returning true if they're different, and false if they're equal. It is a basic building block of the conditions used by commands such as If, when(), and While. The results of ≠ and the other relational operators (=, >, , <, and ) can be combined with the and, or, xor, and not operators to create more complicated conditions.

It returns a single value for most types of data, and returns true if the two sides are mismatched in type: comparing a single number to a list, for instance, or comparing two lists that are of a different size. The only exception is when comparing two lists or two matrices of the same size: in that case, it compares them element-by-element, and returns a list or matrix of true/false values.

:2+2≠4
           false
:2+2≠5
           true
:{1,2,3}≠{1,4,3}
           {false  true  false}

If either side or both contains undefined variables, ≠ will wait to return a value unless it's something clearly true or false for any value of the variable (for instance, x≠x). You can do math with the resulting inequality: if an operation makes sense, it will be applied to both sides: for instance, if x≠y, then you can negate it to get -x≠-y. An operation will not be applied to both sides if it wouldn't be consistent with the previous inequality: for example, you can't square both sides, since if x≠y it can still be the case that x^2=y^2. You can also extract the two halves of the inequality with left() and right().

Related Commands

  • = (equal)
  • > (greater than)
  • (greater than or equal)
  • < (less than)
  • (less than or equal)

See Also

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


The < Command
LESSTHAN.PNG

Command Summary

Returns true if value1 is less than value2.

Command Syntax

value1<value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. 5 to select <, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The < (less than) operator takes two numbers, variables, or expressions, and tests to see if the first one has a value less than the second one. It will return 1 if it is less than, and 0 if it is not. When determining the order of operations, < will be executed after the math operators, but it will be executed before the logical operators and in the order that it appears from left to right with the other relational operators.

:1<0
           0

:DelVar X3→Y
:X<Y
           1

Advanced Uses

Just like the other relational operators, < can take real numbers and lists for variables. In order to compare the lists, however, both must have the same dimensions; if they don't, the calculator will throw a ERR:DIM MISMATCH error. When comparing a real number to a list, the calculator will actually compare the number against each element in the list and return a list of 1s and 0s accordingly.

:{2,4,6,8}<{1,3,5,7
           {0 0 0 0}
:5<{1,2,3,4,5
           {0 0 0 0 0}

Unfortunately, < does not work with strings, matrices, or complex numbers (only = and do), and the calculator will actually throw a ERR:DATA TYPE error if you try to compare them. In the case of strings, however, it should be pretty obvious why: a string represents a sequence of characters, and does not associate a value to any character, so there is nothing to compare.

Error Conditions

  • ERR:DATA TYPE is thrown if you try to compare strings, matrices, or complex numbers.
  • ERR:DIM MISMATCH is thrown if you try to compare two lists that have different dimensions.

Related Commands

  • = (equal)
  • (not equal)
  • > (greater than)
  • (greater than equal)
  • (less than equal)

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


The < Command

lessthan.png

Command Summary

Tests if one value is smaller than another.

Command Syntax

value1<value 2

Menu Location

Press [2nd][<] to enter <.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The < operator compares two values, returning true if the right side is greater, and false otherwise. It is a basic building block of the conditions used by commands such as If, when(), and While. The results of < and the other relational operators (=, , >, , and ) can be combined with the and, or, xor, and not operators to create more complicated conditions.

It returns a single value for most types of data, and returns false if the two sides are mismatched in type: comparing a single number to a list, for instance, or comparing two lists that are of a different size. The only exception is when comparing two lists or two matrices of the same size: in that case, it compares them element-by-element, and returns a list or matrix of true/false values.

:3<4
           true
:3<2
           false
:{1,2,3}<{3,2,1}
           {true  false  false}

If either side or both contains undefined variables, < will wait to return a value. You can do math with the resulting inequality, and if an operation makes sense, it will be applied to both sides: for instance, if x<y, then you can negate it to get -x>-y. An operation will not be applied to both sides if it wouldn't be consistent with the previous inequality: for example, you can't square both sides, since even if x<y the comparison between x^2 and y^2 could go in any order. You can also extract the two halves of the inequality with left() and right().

Advanced Uses

The < operator can also compare strings. It does so by comparing the character codes of each character, and orders the strings by the first difference it finds. This ideally means that the strings are ordered by dictionary order: for example, "aardvark"<"apple", since it would come later in the dictionary.

However, the problem is that all uppercase letters have a smaller character code than lowercase letters, so this only holds true if the strings are the same case. Otherwise, strange results can happen: for instance, "Apple"<"aardvark", since "A" comes before "a".

Related Commands

  • = (equal)
  • (not equal)
  • > (greater than)
  • (greater than or equal)
  • (less than or equal)

See Also

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


The ≤ Command
LESSTHANEQUAL.PNG

Command Summary

Returns true if value1 is less than or equal to value2.

Command Syntax

value1value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. 6 to select ≤, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ≤ (less than equal) operator takes two numbers, variables, or expressions, and tests to see if the first one has a value less than or equal to the second one. It will return 1 if it is less than or equal to, and 0 if it is not. When determining the order of operations, ≤ will be executed after the math operators, but it will be executed before the logical operators and in the order that it appears from left to right with the other relational operators.

:1≤0
           0

:DelVar X3→Y
:X≤Y
           1

Advanced Uses

Just like the other relational operators, ≤ can take real numbers and lists for variables. In order to compare the lists, however, both must have the same dimensions; if they don't, the calculator will throw a ERR:DIM MISMATCH error. When comparing a real number to a list, the calculator will actually compare the number against each element in the list and return a list of 1s and 0s accordingly.

:{2,4,6,8}≤{1,3,5,7
           {0 0 0 0}
:5≤{1,2,3,4,5
           {0 0 0 0 1}

Unfortunately, ≤ does not work with strings, matrices, or complex numbers (only = and do), and the calculator will actually throw a ERR:DATA TYPE error if you try to compare them. In the case of strings, however, it should be pretty obvious why: a string represents a sequence of characters, and does not associate a value to any character, so there is nothing to compare.

Error Conditions

  • ERR:DATA TYPE is thrown if you try to compare strings, matrices, or complex numbers.
  • ERR:DIM MISMATCH is thrown if you try to compare two lists that have different dimensions.

Related Commands

  • = (equal)
  • (not equal)
  • > (greater than)
  • (greater than equal)
  • < (less than)

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


The ≤ Command

lessthanequal.png

Command Summary

Tests if one value is smaller than or equal to another.

Command Syntax

value1value 2

Menu Location

Press [♦][<] to enter ≤.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ≤ operator compares two values, returning true if the right side is greater or if the two are equal, and false otherwise. It is a basic building block of the conditions used by commands such as If, when(), and While. The results of ≤ and the other relational operators (=, , >, , and <) can be combined with the and, or, xor, and not operators to create more complicated conditions.

It returns a single value for most types of data, and returns false if the two sides are mismatched in type: comparing a single number to a list, for instance, or comparing two lists that are of a different size. The only exception is when comparing two lists or two matrices of the same size: in that case, it compares them element-by-element, and returns a list or matrix of true/false values.

:3≤4
           true
:3≤2
           false
:{1,2,3}≤{3,2,1}
           {true  true  false}

If either side or both contains undefined variables, ≤ will wait to return a value. You can do math with the resulting inequality, and if an operation makes sense, it will be applied to both sides: for instance, if x≤y, then you can negate it to get -x≥-y. An operation will not be applied to both sides if it wouldn't be consistent with the previous inequality: for example, you can't square both sides, since even if x≤y the comparison between x^2 and y^2 could go in any order. You can also extract the two halves of the inequality with left() and right().

Advanced Uses

The ≤ operator can also compare strings. It does so by comparing the character codes of each character, and orders the strings by the first difference it finds. This ideally means that the strings are ordered by dictionary order: for example, "aardvark"≤"apple", since it would come later in the dictionary.

However, the problem is that all uppercase letters have a smaller character code than lowercase letters, so this only holds true if the strings are the same case. Otherwise, strange results can happen: for instance, "Apple"≤"aardvark", since "A" comes before "a".

Related Commands

  • = (equal)
  • (not equal)
  • > (greater than)
  • (greater than or equal)
  • < (less than)

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:less-than-or-equal


The = Command
EQUAL.PNG

Command Summary

Returns true if value1 is equal to value2.

Command Syntax

value1=value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. 1 to select =, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The = (equal) operator takes two numbers, variables, or expressions, and tests to see if they are equal to each other. It will return 1 if they are, and 0 if they are not. When determining the order of operations, = will be executed after the math operators, but it will be executed before the logical operators and in the order that it appears from left to right with the other relational operators.

1=0
           0
0->X
           0
3→Y
           3
X=Y
           0

Advanced Uses

Just like the other relational operators, = can take real numbers and lists for variables. In order to compare the lists, however, both must have the same dimensions; if they don't, the calculator will throw a ERR:DIM MISMATCH error. When comparing a real number to a list, the calculator will actually compare the number against each element in the list and return a list of 1s and 0s accordingly.

{2,4,6,8}={1,3,5,7
           {0 0 0 0}
5={1,2,3,4,5
           {0 0 0 0 1}

Besides real numbers and lists, = also allows you compare strings, matrices, and complex numbers. However, the variables must be of the same type, otherwise the calculator will throw a ERR:DATA TYPE error.

[[1,2,3]]=[[1,2,3
                      1
"HELLO"="WORLD
                      0
(3+4i)=(5-2i)
                      0

When matrices are compared, the result is 1 if the matrices are identical. Both matrices must have the same dimensions, otherwise you will get a ERR:DIM MISMATCH error. Internally, the calculator compares values from the bottom right of each matrix, moving left across each row from bottom to top. If unequal elements are found, the calculator returns 0 without examining the rest of the matrix.

Optimization

When a variable is used in a conditional statement, and the only values that are possible for a variable are 1 and 0, you can get rid of the = sign and simply use the variable by itself.

:If X=1
can be
:If X

Error Conditions

  • ERR:DATA TYPE is thrown if you try to compare two different kinds of variables, such as a string and number or a list and matrix.
  • ERR:DIM MISMATCH is thrown if you try to compare two lists or matrices that have different dimensions.

Related Commands

  • (not equal)
  • > (greater than)
  • (greater than equal)
  • < (less than)
  • (less than equal)

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


The = Command

equal.png

Command Summary

Tests if two values are equal.

Command Syntax

value1=value 2

Menu Location

Press the [=] key to enter =.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The = operator compares two values, returning true if they're equal, and false otherwise. It is a basic building block of the conditions used by commands such as If, when(), and While. The results of = and the other relational operators (, >, , <, and ) can be combined with the and, or, xor, and not operators to create more complicated conditions.

It returns a single value for most types of data, and returns false if the two sides are mismatched in type: comparing a single number to a list, for instance, or comparing two lists that are of a different size. The only exception is when comparing two lists or two matrices of the same size: in that case, it compares them element-by-element, and returns a list or matrix of true/false values.

:2+2=4
           true
:2+2=5
           false
:{1,2,3}={1,4,3}
           {true  false  true}

If either side or both contains undefined variables, = will wait to return a value unless it's something clearly true for any value of the variable (for instance, x=x). You can do math with the resulting equation (most operations will be applied to both sides), and extract the two halves of it with left() and right().

Optimization

Testing "If x=true" is redundant in most cases; you can shorten that to "If x". Similarly, "If x=false" can be "If not x".

Related Commands

  • (not equal)
  • > (greater than)
  • (greater than or equal)
  • < (less than)
  • (less than or equal)

See Also

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


The ≥ Command
GREATERTHANEQUAL.PNG

Command Summary

Returns true if value1 is greater than or equal to value2.

Command Syntax

value1value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. 4 to select ≥, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The (greater than equal) operator takes two numbers, variables, or expressions, and tests to see if the first one has a value greater than or equal to the second one. It will return 1 if it is greater than or equal to, and 0 if it is not. When determining the order of operations, will be executed after the math operators, but it will be executed before the logical operators and in the order that it appears from left to right with the other relational operators.

:1≥0
           1

:DelVar X3→Y
:X≥Y
           0

Advanced Uses

Just like the other relational operators, can take real numbers and lists for variables. In order to compare the lists, however, both must have the same dimensions; if they don't, the calculator will throw a ERR:DIM MISMATCH error. When comparing a real number to a list, the calculator will actually compare the number against each element in the list and return a list of 1s and 0s accordingly.

:{2,4,6,8}≥{1,3,5,7
           {1 1 1 1}
:5≥{1,2,3,4,5
           {1 1 1 1 1}

Unfortunately, does not work with strings, matrices, or complex numbers (only = and do), and the calculator will actually throw a ERR:DATA TYPE error if you try to compare them. In the case of strings, however, it should be pretty obvious why: a string represents a sequence of characters, and does not associate a value to any character, so there is nothing to compare.

Error Conditions

  • ERR:DATA TYPE is thrown if you try to compare strings, matrices, or complex numbers.
  • ERR:DIM MISMATCH is thrown if you try to compare two lists that have different dimensions.

Related Commands

  • = (equal)
  • (not equal)
  • > (greater than)
  • < (less than)
  • (less than equal)

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


The ≥ Command

greaterthanequal.png

Command Summary

Tests if one value is larger than or equal to another.

Command Syntax

value1value 2

Menu Location

Press [♦][>] to enter ≥.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ≥ operator compares two values, returning true if the left side is greater or if the two are equal, and false otherwise. It is a basic building block of the conditions used by commands such as If, when(), and While. The results of ≥ and the other relational operators (=, , >, <, and ) can be combined with the and, or, xor, and not operators to create more complicated conditions.

It returns a single value for most types of data, and returns false if the two sides are mismatched in type: comparing a single number to a list, for instance, or comparing two lists that are of a different size. The only exception is when comparing two lists or two matrices of the same size: in that case, it compares them element-by-element, and returns a list or matrix of true/false values.

:3≥4
           false
:3≥2
           true
:{1,2,3}≥{3,2,1}
           {false  true  true}

If either side or both contains undefined variables, ≥ will wait to return a value. You can do math with the resulting inequality, and if an operation makes sense, it will be applied to both sides: for instance, if x≥y, then you can negate it to get -x≤-y. An operation will not be applied to both sides if it wouldn't be consistent with the previous inequality: for example, you can't square both sides, since even if x≥y the comparison between x^2 and y^2 could go in any order. You can also extract the two halves of the inequality with left() and right().

Advanced Uses

The ≥ operator can also compare strings. It does so by comparing the character codes of each character, and orders the strings by the first difference it finds. This ideally means that the strings are ordered by dictionary order: for example, "apple"≥"aardvark", since it would come later in the dictionary.

However, the problem is that all uppercase letters have a smaller character code than lowercase letters, so this only holds true if the strings are the same case. Otherwise, strange results can happen: for instance, "aardvark"≥"Apple", since "a" comes after "A".

Related Commands

  • = (equal)
  • (not equal)
  • > (greater than)
  • < (less than)
  • (less than or equal)

See Also

For the most up-to-date version of this command, see http://tibasicdev.wikidot.com/68k:greater-than-or-equal


The > Command
GREATERTHAN.PNG

Command Summary

Returns true if value1 is greater than value2.

Command Syntax

value1>value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. 3 to select >, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The > (greater than) operator takes two numbers, variables, or expressions, and tests to see if the first one has a value greater than the second one. It will return 1 if it is greater, and 0 if it is not. When determining the order of operations, > will be executed after the math operators, but it will be executed before the logical operators and in the order that it appears from left to right with the other relational operators.

:1>0
           1

:DelVar X3→Y
:X>Y
           0

Advanced Uses

Just like the other relational operators, > can take real numbers and lists for variables. In order to compare the lists, however, both must have the same dimensions; if they don't, the calculator will throw a ERR:DIM MISMATCH error. When comparing a real number to a list, the calculator will actually compare the number against each element in the list and return a list of 1s and 0s accordingly.

:{2,4,6,8}>{1,3,5,7
           {1 1 1 1}
:5>{1,2,3,4,5
           {1 1 1 1 0}

Unfortunately, > does not work with strings, matrices, or complex numbers (only = and do), and the calculator will actually throw a ERR:DATA TYPE error if you try to compare them. In the case of strings, however, it should be pretty obvious why: a string represents a sequence of characters, and does not associate a value to any character, so there is nothing to compare.

Error Conditions

  • ERR:DATA TYPE is thrown if you try to compare strings, matrices, or complex numbers.
  • ERR:DIM MISMATCH is thrown if you try to compare two lists that have different dimensions.

Related Commands

  • = (equal)
  • (not equal)
  • (greater than equal)
  • < (less than)
  • (less than equal)

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


The > Command

greaterthan.png

Command Summary

Tests if one value is larger than another.

Command Syntax

value1>value 2

Menu Location

Press [2nd][>] to enter >.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The > operator compares two values, returning true if the left side is greater, and false otherwise. It is a basic building block of the conditions used by commands such as If, when(), and While. The results of > and the other relational operators (=, , , <, and ) can be combined with the and, or, xor, and not operators to create more complicated conditions.

It returns a single value for most types of data, and returns false if the two sides are mismatched in type: comparing a single number to a list, for instance, or comparing two lists that are of a different size. The only exception is when comparing two lists or two matrices of the same size: in that case, it compares them element-by-element, and returns a list or matrix of true/false values.

:3>4
           false
:3>2
           true
:{1,2,3}>{3,2,1}
           {false  false  true}

If either side or both contains undefined variables, > will wait to return a value. You can do math with the resulting inequality, and if an operation makes sense, it will be applied to both sides: for instance, if x>y, then you can negate it to get -x<-y. An operation will not be applied to both sides if it wouldn't be consistent with the previous inequality: for example, you can't square both sides, since even if x>y the comparison between x^2 and y^2 could go in any order. You can also extract the two halves of the inequality with left() and right().

Advanced Uses

The > operator can also compare strings. It does so by comparing the character codes of each character, and orders the strings by the first difference it finds. This ideally means that the strings are ordered by dictionary order: for example, "apple">"aardvark", since it would come later in the dictionary.

However, the problem is that all uppercase letters have a smaller character code than lowercase letters, so this only holds true if the strings are the same case. Otherwise, strange results can happen: for instance, "aardvark">"Apple", since "a" comes after "A".

Related Commands

  • = (equal)
  • (not equal)
  • (greater than or equal)
  • < (less than)
  • (less than or equal)

See Also

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


The | Command

with.png

Command Summary

Substitutes a value for a variable temporarily.

Command Syntax

expression

Menu Location

Press the

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The | operator (which nobody seems to know how to pronounce, although TI suggests "with") temporarily sets a variable to some value, just for a single evaluation. For example:

:x^2+2x+1|x=5
           6

Using the | operator doesn't actually affect the value of the variable. However, it will work both if the variable is undefined, and if the variable already has a different value.

Only one | can occur in a single expression: if you have more, this will either cause an error or ignore all but the first substitution, depending on placement. However, one | is enough for any number of variables: just separate the values to use with and:

:x+y|x=2 and y=2
           4

Advanced Uses

The | operator has a more complicated use: rather than giving a specific value for a variable, you might give a condition (or several conditions) for its value, using the >, , <, and operators. This condition will be used if it helps simplify the expression, especially with solve(). For instance:

:abs(x)|x<0
           -x

Weird things can happen if you do this to a variable whose value is already defined, however:

:5→x
           5
:abs(x)|x<0
           |undef|

Optimization

If a complicated expression has a repeating element, you may be able to make the calculation smaller and faster by replacing this repeating element with a variable, for which you substitute the correct value. For example (here the repeating element is √(1-x^2)):

:x√(1-x^2)+tanֿ¹(x/√(1-x^2))

can be

:x*a+tanֿ¹(x/a)|a=√(1-x^2)

A related trick is to make a substitution with a function, for an operation that has to be done several times in a single line. For example:
:a*(a-1)/2+b*(b-1)/2+c*(c-1)/2

can be

:f(a)+f(b)+f(c)|f(x)=x*(x-1)/2

Error Conditions

200 - Constraint expression invalid happens when the condition doesn't make sense to the calculator.

Related Commands

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


The ° Command

degree.png

Command Summary

Converts an angle to degrees, if necessary.

Command Syntax

angle°

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 2 to enter the Angle submenu.
  • Press 1 to select °.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The ° symbol used after an angle makes sure the angle is interpreted as being in degrees. If the calculator is already in degree mode, x° is equal to x; in radian mode, x° is equal to π*x/180; and in gradian mode, x° is equal to 10*x/9.

If you're using degree measure extensively in a program, it's a better idea to use setMode() to switch to degree mode and not worry about this. However, there are two reasons you might want to use °:

  • If you need an angle in degrees only once or twice, don't bother changing the mode setting.
  • In a function, you're forced to use °, since setMode() isn't valid in a function.

In radian mode:

:sin(30)
           sin(30)
:sin(30°)
           1/2
:180°
           π

In degree mode (no conversion is necessary, so no conversion is done):

:sin(30)
           1/2
:sin(30°)
           1/2
:180°
           180

Another possible use of ° is to write an angle in degrees, minutes, and seconds as x°y'z" (using the usual apostrophe and quote symbols) — this stands for x degrees, y minutes (equal to 1/60th of a degree) and z seconds (equal to 1/60th of a minute). There's no "degree/minute/second" mode setting, so an angle entered in this form will always be simplified: first to (x+y/60+z/3600)2 degrees, and then (if necessary) converted to the correct angle measure. However, you can use ▶DMS to express output in this form.

Related Commands

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


The - Command
SUBTRACT.GIF

Command Summary

Returns the difference between two numbers.

Command Syntax

value1 - value2

Menu Location

Press [-]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The - (subtract) operator takes two numbers, variables, or expressions and subtracts one from the other, thus returning the difference between them. The - operator appears lower in the order of operations than both * and /, so if those appear in an expression, they will be executed first. In addition, the + operator has the same order of operations as -, so the calculator simply executes them left to right in the order that they appear.

:1-1
           0

:5→X
:2-3X
           -13

:2→A:3→B
:A/B-B/A
           -.8333333333

Error Conditions

  • ERR:SYNTAX is thrown if you try to use - (subtract) in place of (negative). Because they look very similar, it's easy to get this error; at the same time, it's an easy error to fix.

Related Commands

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


The - Command

subtract.png

Command Summary

Returns the difference of two numbers.

Command Syntax

value1 - value2

Menu Location

Press the [-] key to paste -.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The - operator subtracts two numbers, variables, or expressions. Order of operations dictates that it's calculated after * and /, and at the same time as +.

The - operator can also be used on lists and matrices. For the most part, it behaves in the intuitive way, distributing the operation over each element. However, subtracting a number from a matrix (or a matrix from a number) behaves differently: the number is only subtracted along the main diagonal of the matrix. For "normal" subtraction that applies to every element of the matrix, see .-.

:1-1
           0
:5→x
:2-3x
           -13
:[1,2;3,4]-100
           [-99  2]
           [3  -96]

Related Commands

  • + (add)
  • * (multiply)
  • / (divide)

See Also

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


The ! Command
FACTORIAL.GIF

Command Summary

Calculates the factorial of a number or list.

Command Syntax

value!

Menu Location

Press:

  1. MATH to access the math menu.
  2. LEFT to access the PRB submenu.
  3. 4 to select !, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

! is the factorial function, where n! = n*(n-1)! and 0! = 1, n an nonnegative integer. The function also works for arguments that are half an odd integer and greater than -1/2: $(-\frac1{2})!$ is defined as $\sqrt{\pi}$ and the rest are defined recursively.

3!
     6
(‾.5)!
     1.772453851
Ans²
     3.141592654

The combinatorial interpretation of factorials is the number of ways to arrange n objects in order.

Error Conditions

  • ERR:DOMAIN for any numbers except the ones mentioned above.

Related Commands

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


The ! Command

factorial.png

Command Summary

Takes the factorial of a number.

Command Syntax

number!

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 ! operator takes the factorial of a number: for a positive, whole number, n! is defined as n*(n-1)*(n-2)*…*3*2*1. As a special case, 0! is defined to be 1.

The factorial has a special meaning in combinatorics: n! is the number of ways you can order n objects. For instance, 3!=6 because there are 6 ways to order 3 objects:

  • A B C
  • A C B
  • B A C
  • B C A
  • C A B
  • C B A

As can be expected, factorials get very large very quickly. The calculator can only compute an exact integer result for factorials up to 299!, and an approximate result for factorials up to 449!. Beyond that, the numbers involved are replaced by ∞ (infinity) in expressions.

While there are some formulas to define factorials of non-integer values, the calculator doesn't use them. It will leave an expression like (1/2)! unsimplified. However, the factorial of a number less than or equal to -1 will be "undef".

:5!
           120
:299!
           1020191707388... (600 more digits)
:449!
           3.85193e997
:(-2)!
           undef

Related Commands

See Also

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


The / Command
DIVIDE.GIF

Command Summary

Returns the division of two numbers.

Command Syntax

value1 / value2

Menu Location

Press [/]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The / (divide) operator takes two numbers, variables, or expressions and divides them, thus returning a single new value. The / operator appears higher in the order of operations than both + and -, so if those appear in an expression, / will be executed first. In addition, the * operator has the same order of operations as /, so the calculator simply executes them left to right in the order that they appear.

:1/1
           1

:5→X
:2/3X
           3.333333333

:2→A:3→B
:A/B/B/A
           .1111111111

Related Commands

Error Conditions

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


The / Command

divide.png

Command Summary

Divides one number by another.

Command Syntax

value1 / value2

Menu Location

Press the [/] key to paste /.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The / operator divides two numbers, variables, or expressions. It has higher priority than + and -, so it will be done before them; it has the same priority as *.

:x/y
        x/y
:2/2
        1

Though division by zero isn't allowed, it will not cause an error; instead it returns the value undef — short for "undefined." Dividing by a variable that hasn't been defined yet will cancel it if it occurs on both sides: 5*x/x will equal 5; a short warning will be given to the effect that this isn't valid for x=0.

Related Commands

  • - (subtract)
  • * (multiply)
  • + (add)

See Also

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


The .^ Command

dotpower.png

Command Summary

Raises a value to a power, doing this element-by-element for matrices.

Command Syntax

base .^ exponent

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press 4 to enter the Matrix submenu.
  • Press K to enter the Element ops submenu.
  • Press 1 to select .+.

…frankly, just typing it is way easier.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The .^ operator is generally the same as ^, except when dealing with matrices. While ^ does quite a lot of matrix-specific stuff (check out its page for more information), .^ just applies it element-by-element:

:[a,b;c,d] .^ 2
           [a^2  b^2]
           [c^2  d^2]

The command can handle any choice of matrix and scalar as the base and exponent. However, if you're raising a constant number to a matrix power, be careful that the dot in .^ is not confused for a decimal point, by adding extra spaces:

:2.^[a,b;c,d]
           Error: Data type
:2 .^ [a,b;c,d]
           [2^a  2^b]
           [2^c  2^d]

Although this doesn't come up often, be aware that .^, like ^, is evaluated from right to left: a.^b.^c is calculated as a.^(b.^c), not as (a.^b).^c.

Error Conditions

240 - Dimension mismatch happens when a matrix is raised to the power of another matrix, with different dimensions.

Related Commands

See Also

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


The .- Command

dotsubtract.png

Command Summary

Subtracts two values, using element-by-element subtraction when subtracting a matrix and a number.

Command Syntax

value1 .- value2

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press 4 to enter the Matrix submenu.
  • Press K to enter the Element ops submenu.
  • Press 2 to select .-.

…frankly, just typing it is way easier.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The .- command works like plain - in most cases, taking the difference of two values. It's distinguished by its application to matrices: in particular, when subtracting a matrix and a scalar (in either order). Normally, the operation will be done along the main diagonal only: as though the value were multiplied by the identity matrix. However, .- does the more intuitive thing (for anyone but an algebraist, anyway) and subtracts the value from every element of the matrix (or, if the matrix is being subtracted, subtracts every element from the scalar value).

:[a,b;c,d]-x
        [-x+a  b   ]
        [c     -x+d]
:[a,b;c,d].-x
        [-x+a  -x+b]
        [-x+c  -x+d]

It doesn't really make much sense to use .- to add other kinds of values, but you can do it if you like.

When subtracting a matrix from a constant number, be warned that the . may be interpreted as a decimal point. You can put spaces to help the calculator figure out what you mean.

:5.-[a,b;c,d]
        [-a+5.  -b   ]
        [-c     -d+5.]
:5 .+ [a,b;c,d]
        [-a+5  -b+5]
        [-c+5  -d+5]

Related Commands

  • - (subtract)
  • .+

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


The ./ Command

dotdivide.png

Command Summary

Divides two values, doing so element-by-element for two matrices.

Command Syntax

value ./ value

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press 4 to enter the Matrix submenu.
  • Press K to enter the Element ops submenu.
  • Press 4 to select ./.

…frankly, just typing it is way easier.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ./ operator works just like / in most cases. The only exception is with matrices. The / command can't do anything with then (except for dividing a matrix by a value), but ./ will just apply the operation element-by-element. Obviously, when this is done for two matrices, their dimensions have to match up.

:[a,b;c,d] ./ [e,f;g,h]
           [a/e  b/f]
           [c/g  d/h]

When dividing a constant number by a matrix with ./, you may need to space it out so that there's no confusion between ./ and a decimal point.

:1./[a,b;c,d]
           Error: Data type
:1 ./ [a,b;c,d]
           [1/a  1/b]
           [1/c  1/d]

Error Conditions

240 - Dimension mismatch happens when dividing a matrix by another matrix of a different size.

Related Commands

See Also

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


The .* Command

dotmultiply.png

Command Summary

Multiples two values, using element-by-element multiplication for two matrices.

Command Syntax

value1 .* value2

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press 4 to enter the Matrix submenu.
  • Press K to enter the Element ops submenu.
  • Press 3 to select .*.

…frankly, just typing it is way easier.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

In most cases, .* does the same thing as *. The difference only applies to multiplying two matrices. Whereas * uses the linear-algebra definition (see its article for details), .* does the simple thing and multiplies the matrices element by element (obviously, they must match in size for this to work).

:[1,2;3,4] .* [a,b;c,d]
        [a    2*b]
        [3*c  4*d]

Error Conditions

240 - Dimension mismatch happens when the matrices being multiplied don't match in size.

Related Commands

See Also

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


The .+ Command

dotadd.png

Command Summary

Adds two values, using element-by-element addition when adding a matrix and a number.

Command Syntax

value1 .+ value2

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press 4 to enter the Matrix submenu.
  • Press K to enter the Element ops submenu.
  • Press 1 to select .+.

…frankly, just typing it is way easier.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The .+ command works like plain + in most cases, adding two values together. It's distinguished by its application to matrices: in particular, when adding a matrix and a scalar. Normal addition of a matrix and a single value will add that value along the main diagonal only: as though the value were multiplied by the identity matrix. However, .+ does the more intuitive thing (for anyone but an algebraist, anyway) and adds the value to every element of the matrix.

:[a,b;c,d]+x
        [x+a  b  ]
        [c    x+d]
:[a,b;c,d].+x
        [x+a  x+b]
        [x+c  x+d]

It doesn't really make much sense to use .+ to add other kinds of values, but you can do it if you like.

Although the order of the matrix and the scalar doesn't matter, be warned that in some cases, the . will be interpreted as a decimal point. You can put spaces to help the calculator figure out what you mean.

:5.+[a,b;c,d]
        [a+5.  b   ]
        [c     d+5.]
:5 .+ [a,b;c,d]
        [a+5  b+5]
        [c+5  d+5]

Related Commands

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


The © Command

comment.png

Command Summary

Marks the rest of the line (in a program) as a comment.

Command Syntax

:line of code © comment

Menu Location

Starting in the program editor:

  • Press F2 to enter the I/O menu.
  • Press 9 to select ©.

Calculator Compatibility

This command works on all calculators.

Token Size

4 bytes (+ length of comment)

The © character is used for adding comments in a program: everything after © is ignored by the calculator for the purposes of actually running the program, so it's a good way to make a note to yourself about what a part of your code does. This is especially helpful if you're going to be reading the program later when you don't quite remember what you were doing.

:If ok=0 © If the user pressed ESC
: Stop

There are other situations you might use comments in. For instance, you might make a rough sketch of your program and add comments about the code that has yet to be filled in:

:If key=264 Then
: © add a confirmation dialog here later
: Exit
:EndIf

Yet another use of © is to "comment out" lines of code that you might need later, but want to ignore for now — this is better than deleting the code, since you don't have to rewrite it later.

See Also

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


The * Command
MULTIPLY.GIF

Command Summary

Returns the multiplication of two numbers.

Command Syntax

value1 * value2

Menu Location

Press [*]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The * (multiply) operator takes two numbers, variables, or expressions and multiplies their values together, thus returning a single new value. The * operator appears higher in the order of operations than both + and -, so if those appear in an expression, * will be executed first. In addition, the / operator has the same order of operations as *, so the calculator simply executes them left to right in the order that they appear.

:1*1
           1

:5→X
:2*3X
           30

:2→A:3→B
:A/B*B/A
           1

Advanced Uses

As it turns out, the most advanced way to use * is by not using it at all. On z80-based TI calculators, two adjacent expressions or variables are implicilty multiplied even without a * mark.

:5*A
should be
:5A

:5*cos(N*θ
should be
:5cos(Nθ

There are a few cases in which omitting the multiplication sign doesn't work. For example, 2^4*E3 (which evaluates to 16000) can't be replaced by 2^4E3, since the latter is interpreted as 2^(4000).

Optimization

The * sign has the same truth value as the and operator because they both return zero if one or more of the numbers is zero (based on Boolean logic). Consequently, you sometimes see people implicitly multiplying expressions together in conditionals and loops, instead of joining them together with and. Unfortunately, this is not only usually larger in size, but often times slower.

:If (A=2)(B=7
should be
:If A=2 and B=7

It does save some space when you can avoid using parentheses:

:If A and B
could be
:If AB

Timing

The amount of time taken to multiply two real floating-point numbers varies with the sum of the digits (including in the fractional part) of the right argument. On a 15 MHz calculator, a single multiplication in the worst case (when the right argument is 99999999999999) takes 3.3 ms, the best case (when the right argument is 0) takes about 0.1 ms, and the average case (for fourteen-digit floating point numbers) takes about 1.7 ms.

These timings do not include parser overhead or variable recall time, which are often significant in overall program speed.

Related Commands

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


The * Command

multiply.png

Command Summary

Returns the multiplication of two numbers.

Command Syntax

value1 * value2

Menu Location

Press the [*] key to paste *.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The * operator multiplies two numbers, variables, or expressions. In many cases, it's implied — 5x, for instance, will be assumed to be 5*x. There are two exceptions: long variable names — xy will be interpreted as a single variable, not as x*y — and function calls — f(x) will be interpreted as f() applied to x, not as f*x.

Multiplication has higher priority than + and -, so it will be done before them; it has the same priority as /.

:x*y
        x*y
:2*2
        4

Advanced Uses

Multiplying matrices is not the same as multiplying their individual elements (which the .* operator does). To multiply two matrices, the first must have the same number of columns as the second has rows. The product of an MxN matrix with an NxP matrix will be an MxP matrix, whose (a,b)th entry will be the dot product of the ath row of the first matrix with the bth column of the second.

Error Conditions

240 - Dimension mismatch happens when the dimensions of two matrices don't match up for multiplication to work.

Related Commands

  • - (subtract)
  • + (Add)
  • / (divide)

See Also

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


The & Command

concatenate.png

Command Summary

Joins two strings together.

Command Syntax

string&string

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press D to enter the String submenu.
  • Press 4 to select &.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The & operator joins two strings together, one after the other, returning one large string.

:"Hello"&"World"
           "HelloWorld"
:5→n
:"The value of n is "&string(n)
           "The value of n is 5"

Appending strings is very useful when you want to display text. If you want to display more than one string on the same line, for instance with the Text command, you'll need to use & to combine the strings.

By default, & doesn't put in any separation between the strings, which can look weird: you can see this in the above example, where joining "Hello" and "World" made "HelloWorld". With multiple uses of &, you can put in any separator you like:

:"Hello"&" "&"World"
           "Hello World"

If you want to use & to build up a string from scratch, start with "" — the empty string.

Related Commands

See Also

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


The # Command

indirection.png

Command Summary

Gets a variable given its name as a string.

Command Syntax

#var-name

Menu Location

On a widescreen calculator, press 2nd # to paste #.

Or, on any calculator model, press:

  • 2nd CHAR to enter the CHAR popup menu.
  • 3 to enter the Punctuation submenu.
  • 3 again to paste #.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The # operator takes a string containing a variable name, such as "x", and gives you the variable itself. This can be used to get the value of that variable (kind of like a weaker version of expr()), but the # operator really shines when you need to refer to the variable itself: storing to it, for example. 5→expr("var") will give you an error. 5→#"var", however, will work.

:"x"→str
:5→#str
           5
:x
           5
:DelVar #str
:x
           x

You'll see # called the "indirection" operator (for instance, in the command catalog). This is because using # is an indirect way of accessing a variable's value: you don't have the variable itself to work with, just its name.

Advanced Uses

The # command is particularly useful for dealing with picture variables, if you don't know the exact name of the picture ahead of time. For example, you might have two pictures, called 'cat' and 'dog', that you need to display depending on whether x=1 or x=2. This can be done with an If command, but that gets more and more complicated as you add pictures. On the other hand, you can always do this:

:{"cat","dog"}→pics
:RclPic #(pics[x])

The # command is necessary here because RclPic and commands like it want the actual picture variable as an argument, not a string with its name; expr() wouldn't work either because it would try to find the value of 'cat', and get an error.


Whenever you're dealing with external files created by someone else (such as external levels for a game), you don't know the variable names ahead of time, so you'll need the # operator. For the example of an external level, you would first input the variable name of the level into a string variable (say, the variable 'level'). Then you can use '#level', just as you would a regular variable, to refer to it.

Optimization

In many cases, both # and expr() will do the same thing. In these cases, it's still better to use #, because it's faster.

Error Conditions

360 - Indirection string is not a valid variable name happens when the string used with # isn't allowed as a variable name (e.g. longer than 8 characters).

Related Commands

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


The % Command
PERCENT.GIF

Command Summary

Short for dividing by 100.

Command Syntax

value%

Menu Location

This command can only be accessed through a hex editor (its hex code is 0xBB 0xDA)

Calculator Compatibility

TI-83/84+/SE, OS v1.15+

Token Size

2 bytes

The % symbol is an undocumented command on the TI-83 series calculators starting with OS version 1.15. It's useful as a 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.

Although this trick can save you a few bytes, it also makes your program incompatible with old OS versions — it's up to you to decide if the tradeoff is worth it.

Error Conditions

  • ERR:INVALID is thrown on older operating system versions.

Related Commands

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


The % Command

percent.png

Command Summary

Divides a number by 100.

Command Syntax

number%

Menu Location

  • Press 2nd CHAR to enter the CHAR menu.
  • Press 3 to enter the Punctuation submenu.
  • Press 5 to select %.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The % operator is a cheap shortcut for dividing a number by 100: for instance, 25% = 25/100 = 1/4. When used on a list or matrix, it divides every element by 100.

It's somewhat higher in priority than regular division, so you don't need parentheses as often with it: for instance, 4^50% is equal to 4^(1/2)=2, not to (4^50)%.

Related Commands

  • / (divide)
  • E

See Also

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


The + Command
(1)
\begin{align} {(2^{\lfloor{\log_{2}(x)}\rfloor})}{(3^{\lfloor{\log_{3}(x)}\rfloor})}{(5^{\lfloor{\log_{5}(x)}\rfloor})}{(7^{\lfloor{\log_{7}(x)}\rfloor})}{(11^{\lfloor{\log_{11}(x)}\rfloor})}...{(p^{\lfloor{\log_{p}(x)}\rfloor})} \end{align}
ADD.GIF

Command Summary

Returns the sum of two numbers, or joins two strings together.

Command Syntax

value1 + value2

string1 + string2

Menu Location

Press [+]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The + (add) operator takes two numbers, variables, or expressions and adds their values together, thus returning a single new value. The + operator appears lower in the order of operations than both * and /, so if those appear in an expression, they will be executed first. In addition, the - operator has the same order of operations as +, so the calculator simply executes them left to right in the order that they appear.

:1+1
           2

:5→X
:2+3X
           17

:2→A:3→B
:A/B+B/A
           2.166666667

Advanced Uses

The + operator is overloaded (meaning it has more than one function) by the calculator, and it can be used to put strings together. The strings can consist of whatever combination of text and characters that you want, but it unfortunately does not allow you to join a string to a number (i.e., "Hello5" cannot be made with "Hello"+5).

:"HELLO"+"WORLD
           "HELLOWORLD

:"TI"+"-"+"BASIC
           "TI-BASIC

Related Commands

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


The + Command

add.png

Command Summary

Returns the sum of two numbers.

Command Syntax

value1 + value2

Menu Location

Press the [+] key to paste +.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The + operator adds two numbers, variables, or expressions together. Order of operations dictates that it's calculated after * and /, and at the same time as -.

The + operator can also be used on lists and matrices. For the most part, it behaves in the intuitive way, distributing the operation over each element. However, adding a number to a matrix (in either order) behaves differently: the number is only added along the main diagonal of the matrix. For "normal" addition that applies to every element of the matrix, see .+.

:1+1
           2
:5→x
:2+3*x
           17
:[1,2;3,4]+100
           [101  2]
           [3  104]

Related Commands

  • - (subtract)
  • * (multiply)
  • / (divide)

See Also

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


The → Command
STORE.GIF

Command Summary

Stores a value to a variable.

Command Syntax

ValueVariable

Menu Location

Press [STO►]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The → (store) command will store a number, variable, or expression to a variable, using the respective value(s) of the variable(s) at the time. When storing a value in a variable, you have the value on the left side of → and the variable that it will be stored to on the right side.

:1→X
           1

:{1.3,5.7,9.11→ABC
           {1.3 5.7 9.11}

:"HELLO WORLD→Str1
           "HELLO WORLD"

Advanced

It's not easy to put a → symbol into a string, since "→→Str1 would produce a syntax error (and in general, when the calculator 'sees' a → symbol, it assumes that the string is over, and interprets the symbol literally).

However, you can use Equ►String( (outside a program) to get the → or " symbols in a string:

  1. Type them on the home screen and press [ENTER]
  2. Select 1:Quit when the ERR:SYNTAX comes up.
  3. Press [Y=] to go to the equation editor.
  4. Press [2nd] [ENTRY] to recall the symbols to Y1
  5. Now, use Equ►String(Y1,Str1) to store the symbols to a string.

Optimization

You can remove closing parentheses, braces, brackets, and quotes that are before a → command.

:"Hello"→Str1
can be
:"Hello→Str1

Related Commands

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


The → Command

Command Summary

Stores a value to a variable.

Command Syntax

valuevariable

Menu Location

Press the STO> key to insert →.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The → operator assigns a value to a variable.

Initially, a variable such as 'x', 'lastname', or 'cube' is undefined. When used in an expression, they will be treated as unknowns: 3*x-x may be simplified to 2*x, but will otherwise be left alone.

Once a value is assigned to a variable, that value will be substituted for the variable every time you use it. For example, you might store 5→x. Now, if you write 3*x-x, the answer won't be 2*x, but 10.

Any kind of value — a simple number, an expression, a string, list, or matrix, or even a function can be stored to a variable with →. The following are all valid:

:5→x
           5
:"Alighieri"→lastname
           "Alighieri"
:n^3→cube(n)
           Done

As a special case, you can even store to a single element of a list or matrix. For example:

:{1,2,3,4,5}→list
           {1  2  3  4  5}
:99→list[3]
           99
:list
           {1  2  99  4  5}

Advanced Uses

Using the # (indirection) operator, you can store a value to a variable given its name, in a string.

Optimization

There are alternatives to → such as Define or CopyVar; they have their uses in special situations, but → is better (smaller and easier to understand) in other cases.

Error Conditions

190 - Circular definition happens when an undefined variable is given a value in terms of itself (e.g. x+1→x).

Related Commands

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


The ‾ Command
NEGATIVE.GIF

Command Summary

Returns the negative value of a number.

Command Syntax

value

Menu Location

Press [(-)]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ‾ (negative) operator takes one number, variable, or expression and negates its value, thus returning the negative equivalent of it. The ‾ operator appears higher in the order of operations than both the relational and logical operators, so it will be executed first. In addition, it has the same order of operation as the other math operators, so the calculator simply executes them left to right in the order that they appear.

:‾1
           -1

:5→X
:‾3(X+2
           -21

:‾2→A:‾3→B
:AB
           6

Optimization

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 ‾ sign and save a byte.

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

This is not always the case, however: if you subtract a command that uses a lot of parentheses and is followed by a newline/colon/STO→ arrow, it'd save space to put the subtraction at the beginning of the line. For instance:
:inString(Ans,sub(Str1,1,1+int(log(A))))-1
can be
:‾1+inString(Ans,sub(Str1,1,1+int(log(A

Error Conditions

If an ERR:SYNTAX is being thrown near a subtraction or negation where there should be no errors, check to make sure that ‾ (negation) and - (subtraction) were not swapped by mistake.

Related Commands

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


The ‾ Command

negative.png

Command Summary

Negates an expression.

Command Syntax

expression

Menu Location

Press the ‾ key to enter ‾.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ‾ operator gives the negative of the value immediately following it. It's not to be confused with the - operator, which subtracts two numbers — while on paper you'd generally use the same symbol for -2 and 4-2, the calculator has two different symbols, and negation is represented by the slightly shorter and higher dash.

You can also use ‾ to negate lists and matrices, which will negate each element, as expected.

:1+‾1
           0
:‾(x-1)
           ‾x+1
:‾[1,2;3,4]
           [‾1  ‾2]
           [‾3  ‾4]

Other pages on this site will use - to mean both subtraction and negation, where it isn't confusing.

Related Commands

  • + (add)
  • - (subtract)

See Also

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


The ∟ Command
L.GIF

Command Summary

Indicates the beginning of a custom list.

Command Syntax

LISTNAME

Menu Location

While editing a program, press:

  1. 2nd LIST to access the List menu
  2. RIGHT to access the OPS submenu
  3. 2nd B to select ∟, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ∟ command indicates the beginning of a custom list (i.e., any list the user creates, not including the default lists L1…L6). You almost always need to include this when accessing or manipulating a custom list. The maximum length of the list name (not including the ∟) is five letters. ∟ABCDE works, but ∟ABCDEF does not.

Optimization

You don't need to include the ∟ command when storing (→) to a list. Some of the list commands also allow for this optimization, such as SetUpEditor. However, it can create problems when using Input and Prompt because you might only be asking the user to input a list, but a real variable would also be allowed.

Error Conditions

  • ERR:UNDEFINED is thrown if you try to use ∟ on an undefined list.

Related Commands

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


The ∠ Command

angle-symbol.png

Command Summary

Used in entering a vector in polar, cylindrical, or spherical format, or a complex number in polar form.

Command Syntax

[r,∠θ]
[r,∠θ,z]
[r,∠θ,∠φ]
(rθ)

Menu Location

  • Press 2nd MATH to enter the MATH menu.
  • Press 2 to enter the Angle submenu.
  • Press 7 to select ∠.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ∠ operator is used for alternate forms of entering vectors or complex numbers. It will be used for output depending on the Complex Format and Vector Format mode settings, but you can always use it in an expression.

For vectors (which are just 1x2 or 1x3 matrices, as far as ∠ is concerned):

  • [r,∠θ] is equivalent to [r*cos(θ),r*sin(θ)]
  • [r,∠θ,z] is equivalent to [r*cos(θ),r*sin(θ),z]
  • [r,∠θ,∠φ] is equivalent to [r*cos(θ)*sin(φ),r*sin(θ)*sin(φ),r*cos(φ)]

These have to be row vectors — you can't use column vectors with ∠.

For complex numbers, (r∠θ) is equivalent to r*(cos(θ)+i*sin(θ)). You have to have the parentheses there, and both r and θ must be real numbers or expressions.

Error Conditions

260 - Domain error happens when complex numbers are used in the vector notation.

580 - Invalid polar complex happens when the values of r and θ in the complex number notation are invalid.

640 - Invalid vector syntax happens when the ∠ mark is misplaced in the vector notation.

Related Commands

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


The ▶ Command

convert.png

Command Summary

Converts an expression from one unit to another.

Command Syntax

expressionunits

Menu Location

Press [2nd][▶] to enter ▶: this is

  • [2nd][MODE] on a TI-89 or TI-89 Titanium
  • [2nd][Y] on a TI-92, TI-92 Plus, or Voyage 200

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The ▶ operator converts an expression to a different unit. Usually, this refers to the built-in units (such as _m (meters), _mph (miles per hour, etc.) which you can select from the UNITS menu.

To use it, you must first have the expression on the left in terms of some unit — this is done by multiplying it by that unit. For instance, "5 meters" is written as 5_m or 5*_m (where _m is the unit). You can combine units as well: for instance, 5_m^2 (5 square meters) or 30_km/_hr (30 kilometers per hour).

To convert that into a different unit, type ▶ and then a different unit to convert to (again, you can combine units). For instance, to convert 5 square meters to acres, type 5_m^2▶_acre. (Note: the result will always be expressed as a decimal)

:30_km/_hr▶_m/_s
           8.33333*_m/_s
:5_N▶_dyne
           500000.*_dyne

You can't use ▶ to convert between units of temperature (degrees Celsius to degrees Fahrenheit, for instance), since the calculator isn't sure if you mean absolute temperature or a change in temperature instead. Use the tmpCnv() and ΔtmpCnv() commands instead.

Advanced Uses

It's possible to define your own units as well: units are just any variable beginning with an underscore, and ▶ will perform just as well converting between those. There are two ways to go about it. The first is to define your units in terms of existing ones: for instance, you might define a furlong (one-eighth of a mile) as follows:

:1/8_mi→_furlong
           1/8*_mi
:110_yd▶_furlong
           .5*_furlong

The second method is to start with a unit or several units to keep undefined (for instance, _x). You can then define other units in terms of _x, and convert between them:
:5_x→_y
           5*_x
:3_y▶_x
           15.*_x
:10_x/_s▶_y/_s
           2.*_y/_s

Units are treated just like variables, except that they're universal across folders: you can have only one instance of _x, and you can access it as _x no matter which folder you're in. You can use this if you want to define a universal variable to access in any folder: for instance, if you define a program as _prgm(), you can run it with _prgm() from any folder.

Error Conditions

345 - Inconsistent units happens when converting between two units that measure different types of quantities (for instance, converting length to time).

Related Commands

See Also

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


The √( Command
SQUAREROOT.PNG

Command Summary

Take the square root of a number.

Command Syntax

√(input)

Menu Location

Press 2nd √ to paste the √( command.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

Takes the square root of a positive or negative number. It works exactly the same as 2×√ or ^(1/2) but is smaller and uses an ending parenthesis. If used on a list, it will return a list with the square root of each element.

√(4)
        2
√(2)
        1.414213562

√({1,-1})
        {1 i}

This may return a complex number or throw ERR:NONREAL ANS (depending on mode settings) if taking the square root of a negative number.

Optimization

Never raise something to the one-half power explicitly; use this command instead.

:X^(1/2)→X
can be
:√(X→X

Error Conditions

Related Commands

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


The ∏() Command

product-pi.png

Command Summary

Multiplies together the evaluations of an expression with one variable taking on a range of values.

Command Syntax

∏(expression, variable, start, end)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press B to enter the Calculus submenu.
  • Press 5 to select ∏(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

∏() is used to multiply a sequence of numbers. ∏(expression, variable, start, end) will evaluate expression for variable=start, then for variable=start+1, all the way through variable=end, and multiply the results:

:∏(f(x),x,1,5)
           f(1)*f(2)*f(3)*f(4)*f(5)
:∏(x,x,1,5)
           120

In this way, ∏() is no different from taking product() of a sequence generated by seq(). However, ∏() can be used for more abstract calculations — for instance, when start or end is an undefined variable, it will try to find the product in terms of that variable. ∏() can also be used to find the product of an infinite series (just make the value of end infinity — ∞).

:∏(x,x,1,n)
           n!
:∏(1-1/x,x,2,n)
           1/n

Related Commands

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


The ∑() Command

sum-sigma.png

Command Summary

Adds together the evaluations of an expression with one variable taking on a range of values.

Command Syntax

∑(expression, variable, start, end)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press B to enter the Calculus submenu.
  • Press 4 to select ∑(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

∑() is used to add a sequence of numbers. ∑(expression, variable, start, end) will evaluate expression for variable=start, then for variable=start+1, all the way through variable=end, and add up the results:

:∑(f(x),x,1,5)
           f(1)+f(2)+f(3)+f(4)+f(5)
:∑(x^2,x,1,5)
           55

In this way, ∑() is no different from taking sum() of a sequence generated by seq(). However, ∑() can be used for more abstract calculations — for instance, when start or end is an undefined variable, it will try to find the sum in terms of that variable. ∑() can also be used to sum an infinite series (just make the value of end infinity — ∞).

:∑(x^2,x,1,n)
           n*(n+1)*(2*n+1)/6           
:∑(2^-x,x,1,∞)
           1

Optimization

It's a good idea to replace sum(seq( by ∑( whenever it occurs. The only difficulty arises if seq() uses its step argument, since ∑() doesn't have one. There are three options:

  • Forget about using ∑() and just go with the sum(seq( alternative.
  • Use a when() expression (probably with mod()) to select the entries you care about.
  • Use a linear equation to transform values from 1 to N into the correct values with the step.

Here is an example of these approaches:

:sum(seq(x^2,x,1,9,2))

This calculates 12+32+52+72+92.
:∑(when(mod(x,2)=1,x^2,0),x,1,9)

The when() command selects only the odd numbers — those with mod(x,2)=1 — from 1 to 9.
:∑((2x-1)^2,x,1,5)

The equation 2*x-1 transforms the numbers 1..5 into the odd numbers 1..9.

Related Commands

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


The √() Command

square-root.png

Command Summary

Takes the square root of a number.

Command Syntax

√(number)

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 √() command takes the square root of a value: √(x) is a number that, when multiplied by itself, gives x. It's a special case of the ^ and root() commands: √(x) = x^(1/2) = root(x,2).

Unless the calculator is in approximate mode, or you force it to approximate (by pressing ♦+ENTER, or using approx()), it won't try to evaluate all square roots: it will take the square root of perfect squares, otherwise, it will just take out all the square factors (for instance, √(20) is simplified to 2√(5)).

For positive numbers, √() will return the positive square root; more generally, if the result is complex (and if the calculator is in complex number mode), the result of √() will be the one with non-negative real part.

:√(16)
           4
:√(-12)
           2*√(3)*i

If the square root of a list is taken, it will take the square root of every element of the list.

Advanced Uses

The √() of a matrix is not (in general) the same as taking the square root of every element of the matrix. A different definition is used to compute the result; see Matrices and Their Commands. It requires the matrix to be square and diagonalizable in order to apply.

Error Conditions

230 - Dimension happens when taking the square root of a non-square matrix.

665 - Matrix not diagonalizable happens when diagonalization (used to take square roots of matrices) fails.

800 - Non-real result happens when taking the square root of a negative or complex number, in real number mode.

Related Commands

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


The ∫() Command

integral.png

Command Summary

Takes the integral of an expression.

Command Syntax

∫(expression,variable)
∫(expression,variable,constant)
∫(expression,variable,lower,upper)

Menu Location

Press [2nd][7] to enter ∫(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

∫(expression,variable) takes the integral of expression (symbolically) with respect to variable. All other variables are treated as constant.

There are three ways to use ∫(). The syntax above returns an indefinite integral. ∫(expression,variable,c) does the same, but with a constant of integration, c (this will just get added on to the result). Finally, ∫(expression,variable,a,b) takes a definite integral from a to b. These limits can be anything, including undefined variables, ∞ and -∞, as long as they don't depend on variable.

:∫(x^2,x)
           x^3/3
:∫(x^2,x,c)
           x^3/3+c
:∫(x^2,x,a,b)
           b^3/3-a^3/3

Indefinite integrals are always computed exactly or not at all: if a part of the expression (or the entire expression) can't be integrated, the result will stay in terms of ∫(). However, definite integrals will sometimes be approximated, depending on the Exact/Approx mode setting:

  • If EXACT, integrals will never be approximated.
  • If AUTO, the calculator will approximate integrals like ∫(e^(-x^2),x,-1,1) that it can't compute exactly.
  • If APPROX, all definite integrals will be done numerically if possible.
:∫(e^(-x^2),x)
           ∫(e^(-x^2),x)
:∫(e^(-x^2),x,-1,1)
           2*∫(e^(-x^2),x,0,1) (in EXACT mode)
           1.49365 (in AUTO or APPROX mode)

Finally, you can take multiple integrals by applying ∫() to the result of another ∫() (any number of times). The integration limits of the inner integrals can involve the variables of the outer integrals.

:∫(∫(x*y,x),y)
           y^2*x^2/4
:∫(∫(x*y,x,0,y),y,0,1)
           1/8

If the expression is a list or matrix, ∫() takes the integral of each element.

Error Conditions

140 - Argument must be a variable name happens when the variable of integration isn't a variable.

220 - Dependent limit happens when the integration limits depend on the variable of integration.

Related Commands

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


The ° (Degree Symbol) Command
DEGREE%20(SYMBOL).GIF

Command Summary

If the calculator is in radian mode, the ° (degree) symbol converts an angle to radians.

Command Syntax

angle°

Menu Location

Press:

  1. [2nd]
  2. [Angle]
  3. [Enter] or [1]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

Normally, when the calculator is in radian mode, the trigonometric functions only return values calculated in radians. With the ° symbol you can have the angle evaluated as if in degree mode because it converts the angle into radians.

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 radian mode:

sin(45)        \\ actually calculating sin(2578.31)
    .8509035245
sin(45°)
    .7071067812

In degree mode:
sin(45)
    .7071067812
sin(45°)
    .7071067812    \\ There's no difference when in degrees

Optimization

When you only call the trig function once in a program and want it calculated in degrees, instead of changing the mode you can just use ° to save one-byte (the newline from using the command Degree)

:Degree
:sin(X)
can be
:sin(X°)

Related Commands

  • r (radian symbol)

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


The 0b Command

0b.png

Command Summary

Indicates that a number is written in binary.

Command Syntax

0bdigits

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 calculator can work with numbers written in three bases: decimal (the usual), binary, and hexadecimal. The 0b command indicates that a number is written in binary:

:0b101
           5
:0b100000
           32

When written in binary, numbers are expressed as signed 32-bit integers, which means that only the integers between -231 and 231-1 can be expressed in binary. With other binary-related commands, numbers are simply truncated to fit in this range. Not so with 0b: if you enter more than 32 binary digits after the 0b, the result is a domain error.

Even if the calculator is in binary mode, you still have to write 0b for an integer to be interpreted as binary: binary mode only affects output. If the calculator is in decimal mode, which is the default, you have to use ▶Bin to get output in binary.

Error Conditions

260 - Domain error happens when 0b is used with more than 32 binary digits after it.

Related Commands

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


The 0h Command

0h.png

Command Summary

Indicates that a number is written in hexadecimal.

Command Syntax

0hdigits

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 calculator can work with numbers written in three bases: decimal (the usual), binary, and hexadecimal. The 0h command indicates that a number is written in hexadecimal:

:0h10
           16
:0h2F6
           758

When written in hexadecimal, numbers are expressed as signed 32-bit integers (32 bits correspond to 8 hexadecimal digits), which means that only the integers between -231 and 231-1 can be expressed in hexadecimal. With other hexadecimal-related commands, numbers are simply truncated to fit in this range. Not so with 0h: if you enter more than 8 hexadecimal digits after the 0b, the result is a domain error.

Even if the calculator is in hexadecimal mode, you still have to write 0h for an integer to be interpreted as hexadecimal: the mode setting only affects output. If the calculator is in decimal mode, which is the default, you have to use ▶Hex to get output in hexadecimal.

Error Conditions

260 - Domain error happens when 0h is used with more than 8 hexadecimal digits after it.

Related Commands

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


The 10^( Command
TENPOWER.PNG

Command Summary

Raises 10 to a power.

Command Syntax

10^(value)

Menu Location

Press [2nd] [10x] to paste 10^(.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The 10^( command raises 10 to a power. Since it's possible to just type out 1, 0, ^, and (, the reason for having a separate function isn't immediately obvious, but the command is occasionally useful.

10^( accepts numbers and lists as arguments. It also works for complex numbers.

10^(2)
     100
10^({-1,0,1})
     {0.1 1 10}

Optimization

Don't type 10^( out, use this command instead. It's three bytes smaller and usually faster as well. However, keep in mind that you might be able to use the E command instead of 10^(, for constant values.

Command Timings

The command 10^( is faster than typing out 10^( in most cases, except for small integer arguments. Even faster is E, but that only works for raising 10 to a constant power.

Related Commands

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


The ֿ¹ Command
INVERSE.GIF

Command Summary

Returns the reciprocal of a number (1 divided by the number). For matrices, finds the matrix inverse.

Command Syntax

valueֿ¹

Menu Location

Press [xֿ¹]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ֿ¹ command returns the reciprocal of a number, equivalent to dividing 1 by the number (although reciprocals are sometimes more convenient to type). It also works for lists, by calculating the reciprocal of each element.

The ֿ¹ command can also be used on matrices, but it is the matrix inverse that is computed, not the reciprocal of each element. If [A] is an N by N (square) matrix, then [A]ֿ¹ is the N by N matrix such that [A][A]ֿ¹=[A]ֿ¹[A] is the identity matrix. ֿ¹ does not work on non-square matrices.

4ֿ¹
        .25
{1,2,3}ֿ¹
        {1 .5 .3333333333}
[[3,2][4,3]]ֿ¹
        [[3  -2]
         [-4 3 ]]

Much like the number 0 does not have a reciprocal, some square matrices do not have inverses (they are called singular matrices) and you'll get an error when you try to invert them.

Optimization

Writing Aֿ¹B instead of B/A is sometimes beneficial when B is a complicated expression, because it allows you to take off closing parentheses of B. For example:

:(P+√(P²-4Q))/2
can be
:2ֿ¹(P+√(P²-4Q

This may be slower than dividing. There are also situations in which this optimization might lose precision, especially when the number being divided is large:

7fPart(4292/7
        1
7fPart(7ֿ¹4292
        .9999999999

Error Conditions

Related Commands

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


The 1-PropZInt( Command
1-PROPZINT.GIF

Command Summary

Computes a Z confidence interval of a proportion.

Command Syntax

1-PropZInt(x, n[, confidence level])

Menu Location

When editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. ALPHA A to select 1-PropZInt(, or use arrows

(this key sequence will give you the 1-PropZInt… screen outside a program)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The 1-PropZInt( command calculates a confidence interval for a proportion, at a specific confidence level: for example, if the confidence level is 95%, you are 95% certain that the proportion lies within the interval you get. The command assumes that the sample is large enough that the normal approximation to binomial distributions is valid: this is true if, in the sample you take, the positive and negative counts are both >5.

The 1-PropZInt( command takes 3 arguments. The first, x, is the positive count in the sample. The second, n, is the total size of the sample. (So the sample proportion is equal to x out of n). The third argument is the confidence level, which defaults to 95.

The output gives you a confidence interval of the form (a,b), meaning that the true proportion π is most likely in the range a<π<b, and the value of x/n.

Sample Problem

You want to know the proportion of students at your school that support a particular political candidate. You take a random sample of 50 students, and find that 22 of them support that candidate. 22, the positive count, and 50-22=28, the negative count, are both >5, so the assumption is satisfied.

Using 22 for x, and 50 for n, you decide to find a 95% confidence interval. The syntax for that is:

:1-PropZInt(22,50,95
which can also be
:1-PropZInt(22,50,.95

The output if you run the above code will look approximately like this:
1-PropZInt
 (.30241,.57759)
 p=.44
 n=50

This tells you that between about 30.2% and about 57.8% of the students at your school are in support of the political candidate.

Optimization

If the confidence level is 95%, you can omit the final 95, since that is the default value:

:1-PropZInt(22,50,95
can be
:1-PropZInt(22,50

Error Conditions

  • ERR:DOMAIN is thrown if the sample proportion is not between 0 and 1, any argument is negative, or the confidence level is 100 or more.

Related Commands

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


The 1-PropZTest( Command
1-PROPZTEST.GIF

Command Summary

Performs a z-test on a proportion.

Command Syntax

1-PropZTest(p0, x, n[, alternative, draw?] )

Menu Location

While editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. 5 to select 1-PropZTest, or use arrows

(outside the program editor, this will select the 1-PropZTest… interactive solver)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

1-PropZTest performs an z-test to compare a population proportion to a hypothesis value. This test is valid for sufficiently large samples: only when the number of successes (x in the command syntax) and the number of failures (n-x) are both >5.

The logic behind the test is as follows: we want to test the hypothesis that the true proportion is equal to some value p0 (the null hypothesis). To do this, we assume that this "null hypothesis" is true, and calculate the probability that the (usually, somewhat different) actual proportion occurred, under this assumption. If this probability is sufficiently low (usually, 5% is the cutoff point), we conclude that since it's so unlikely that the data could have occurred under the null hypothesis, the null hypothesis must be false, and therefore the true proportion is not equal to p0. If, on the other hand, the probability is not too low, we conclude that the data may well have occurred under the null hypothesis, and therefore there's no reason to reject it.

Commonly used notation has the letter π being used for the true population proportion (making the null hypothesis be π=p0). TI must have been afraid that this would be confused with the real number π, so on the calculator, "prop" is used everywhere instead.

In addition to the null hypothesis, we must have an alternative hypothesis as well - usually this is simply that the proportion is not equal to p0. However, in certain cases, our alternative hypothesis may be that the proportion is greater or less than p0.

The arguments to 1-PropZTest( are as follows:

  • p0 - the value for the null hypothesis (the proportion you're testing for)
  • x - the success count in the sample
  • n - the total size of the sample (so the sample proportion would be x/n)
  • alternative (optional if you don't include draw?) - determines the alternative hypothesis
    • 0 (default value) - prop≠p0
    • -1 (or any negative value) - prop<p0
    • 1 (or any positive value) - prop>p0
  • draw? (optional) set this to 1 if you want a graphical rather than numeric result

Although you can access the 1-PropZTest command on the home screen, via the catalog, there's no need: the 1-PropZTest… interactive solver, found in the statistics menu, is much more intuitive to use - you don't have to memorize the syntax.

In either case, it's important to understand the output of 1-PropZTest. Here are the meanings of each line:

  • The first line, involving "prop" and p0, is the alternative hypothesis.
  • z is the test statistic. If the null hypothesis is true, it should be close to 0.
  • p is the probability that the difference between the proportion and p0 would occur if the null hypothesis is true. When the value is sufficiently small, we reject the null hypothesis and conclude that the alternative hypothesis is true. You should have a cutoff value ready, such as 5% or 1%. If p is lower, you "reject the null hypothesis on a 5% (or 1%) level" in technical terms.
  • p-hat is the sample proportion, x/n.
  • n is the sample size.

Advanced Uses

The final optional argument of 1-PropZTest, draw?, will display the results in a graphical manner if you put in "1" for it. The calculator will draw the standard normal distribution, and shade the area of the graph that corresponds to the probability p. In addition, the value of z and the value of p will be displayed. You would make your conclusions in the same way as for the regular output.

Optimization

Some of the arguments of the 1-PropZTest command have default values, and the argument can be omitted if this value is used.

  • The draw? argument can be omitted if you don't want graphical output, although you could put "0" in as well.
  • If the above argument is omitted, and you're doing a two sided test, you may omit the alternative argument.

Example:

:1-PropZTest(.5,22,50,0,0
can be
:1-PropZTest(.5,22,50

Error Conditions

  • ERR:DOMAIN is thrown if p0 or x/n are not between 0 and 1, or x is negative or greater than n (however, any real value for alternative and draw? will work)

Related Commands

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


The 1-Var Stats Command
1-VARSTATS.GIF

Command Summary

Calculates some statistics for a single list of data, and stores them to statistical variables. They're also displayed in a scrollable list, if done outside a program.

Command Syntax

1-Var Stats [list, [freqlist]]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 1 or ENTER to select 1-Var Stats

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

This command calculates a bunch of common (and a few uncommon) statistics for a list (it uses L1 by default, but you can use any list by supplying it as an argument). You have to store the list to a variable first, though, before calculating statistics for it. For example:

:{5,12,7,8,4,9→L1
:1-Var Stats

Like other statistical commands, you can use a frequency list as well, for cases where one element occurs more times than another (you can do this with a normal list, too, but that might be inconvenient when an element occurs very many times). For example:

:{1,2,3→L1
:{5,3,2→L2
:1-Var Stats L1,L2

is the frequency-list equivalent of:
:{1,1,1,1,1,2,2,2,3,3→L1
:1-Var Stats

When you're running it from the home screen, 1-Var Stats will display the statistics; this won't happen if you do it inside a program. Either way, it will also store what it calculated to the statistics variables found in VARS>Statistics… The variables 1-Var Stats affects are:

  • $\overline{\textrm{x}}$ is the mean (average) of the elements, as returned by mean(
  • Σx is the sum of the elements, as returned by sum(
  • Σx² is the sum of the squares of the elements
  • Sx is the sample standard deviation, as returned by stdDev(
  • σx is population standard deviation
  • n is the number of elements in the list, as returned by dim(
  • minX is the minimum value, as returned by min(
  • Q1 is the first quartile
  • Med is the median, as returned by median(
  • Q3 is the third quartile
  • maxX is the maximum value, as returned by max(

1-Var Stats will not work with "reserved" list names that the calculator uses internally. The only known such reserved list is the list RESID, and there's no reason to suspect there are any others. Ans, TblInput, and any expression which resolves to a list, are also not appropriate for this command: store all of these to a list before doing 1-Var Stats on them.

Optimization

Aside from statistical analysis, 1-Var Stats can also be used when you want to use the values it calculates more than once. This will save on size, since, for example Σx takes up less space than sum(L1), but considering how many calculations 1-Var Stats makes, it will usually be slower. Here's a short example which saves 1 byte:

:Disp "RANGE:",max(L1)-min(L1
can be
:1-Var Stats
:Disp "RANGE:",maxX-minX

Related Commands

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


The ² Command
SQUARE.GIF

Command Summary

Raises the input to the second power.

Command Syntax

value²

Menu Location

Press [x²]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ² command raises an input to the second power. It has exactly the same function as "^2", but is one byte smaller. If used on a list, it will return a list with all of the elements squared. If used on a matrix, it will return the second matrix power of the input matrix.

2²
        4
{1,‾2,3}²
        {1 4 9}
[[2,‾1][‾3,0]]²
        [[1  ‾2]
         [6 ‾3]]

Optimization

Use this command instead of ^2 in all instances.

:X^2
can be
:X²

Related Commands

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


The 2-PropZInt( Command
2-PROPZINT.GIF

Command Summary

Computes a Z confidence interval of the difference between two proportions.

Command Syntax

2-PropZInt(x1, n1, x2, n2, level//

Menu Location

When editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. ALPHA B to select 2-PropZInt(, or use arrows

(this key sequence will give you the 2-PropZInt… screen outside a program)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The 2-PropZInt( command calculates a confidence interval for the difference between two proportions, at a specific confidence level: for example, if the confidence level is 95%, you are 95% certain that the difference lies within the interval you get. The command assumes that the sample is large enough that the normal approximation to binomial distributions is valid: this is true if, in both samples involved, the positive and negative counts are both >5.

The 1-PropZInt( command takes 5 arguments. The first two, x1 and n1 are the positive count and total count in the first sample (so the estimated value of the first proportion is x1 out of n1. The next two arguments, x2 and n2, are the positive count and total count in the second sample.

The output gives you a confidence interval of the form (a,b), which is the range of values for the difference π12 (where π1 and π2 are the first and second proportions respectively). If you were looking for the difference π21 all you have to do is switch two sides and negate the numbers in the interval.

Sample Problem

You want to compare the proportion of students at your school and at a friend's school. that support a particular political candidate. You take a random sample of 50 students, and find that 22 of them support that candidate. Your friend took a random sample of 75 students at his school, and found that 28 supported the candidate.

The first proportion is the proportion of supporters at your school. 22 out of 50 students support the candidate, so x1=22 and n1=50.
The second proportion is the proportion of supporters at your friend's school. 28 out of 75 students support the candidate, so x2=28 and n2=75.
If you decided to do a 95% confidence interval, you would add the argument 95 after all these, so the syntax would be as follows:

:2-PropZInt(22,50,28,75,95
which can also be
:2-PropZInt(22,50,28,75,.95

The output if you run the above code will look approximately like this:
1-PropZInt
 (-.1092,.24249)
 p1=.44
 p2=.3733333333
 n1=50
 n2=75

This tells you that between about the difference betwen the proportions is between about -0.11 (your school's proportion being about 0.11 less than your friend's school's proportion) to about 0.24 (your school's proportion being about 0.24 greater than your friend's school's proportion).

Optimization

If the confidence level is 95%, you can omit the final 95, since that is the default value:

:2-PropZInt(22,50,28,75,95
can be
:2-PropZInt(22,50,28,75

Error Conditions

  • ERR:DOMAIN is thrown if either proportion is not between 0 and 1, or xi is negative or greater than ni, or the confidence level is negative or at least 100.

Related Commands

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


The 2-PropZTest( Command
2-PROPZTEST.GIF

Command Summary

Performs a z-test to compare two proportions.

Command Syntax

2-PropZTest(x1, n1, x2, n2, //draw?//

Menu Location

While editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. 6 to select 2-PropZTest, or use arrows

(outside the program editor, this will select the 2-PropZTest… interactive solver)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

2-PropZTest performs an z-test to compare two population proportions. This test is valid for sufficiently large samples: only when the number of successes (x in the command syntax) and the number of failures (n-x) are both >5, for both populations.

The logic behind the test is as follows: we want to test the hypothesis that the proportions are equal (the null hypothesis). To do this, we assume that this "null hypothesis" is true, and calculate the probability that the differences between the two proportions occurred, under this assumption. If this probability is sufficiently low (usually, 5% is the cutoff point), we conclude that since it's so unlikely that the data could have occurred under the null hypothesis, the null hypothesis must be false, and therefore the proportions are not equal. If, on the other hand, the probability is not too low, we conclude that the data may well have occurred under the null hypothesis, and therefore there's no reason to reject it.

Commonly used notation has the letters π1 and π2 being used for the true population proportions (making the null hypothesis be π12). TI must have been afraid that this would be confused with the real number π, so on the calculator, "p1" and "p2" are used everywhere instead.

In addition to the null hypothesis, we must have an alternative hypothesis as well - usually this is simply that the proportions are not equal. However, in certain cases, our alternative hypothesis may be that one proportion is greater or less than the other.

The arguments to 1-PropZTest( are as follows:

  • x1 - the success count in the first sample
  • n1 - the total size of the first sample (so the sample proportion would be x1/n1)
  • x2 - the success count in the second sample
  • n2 - the total size of the second sample (so the sample proportion would be x2/n2)
  • alternative (optional if you don't include draw?) - determines the alternative hypothesis
    • 0 (default value) - p1≠p2
    • -1 (or any negative value) - p1<p2
    • 1 (or any positive value) - p1>p2
  • draw? (optional) set this to 1 if you want a graphical rather than numeric result

Although you can access the 1-PropZTest command on the home screen, via the catalog, there's no need: the 1-PropZTest… interactive solver, found in the statistics menu, is much more intuitive to use - you don't have to memorize the syntax.

In either case, it's important to understand the output of 1-PropZTest. Here are the meanings of each line:

  • The first line, involving p1 and p2, is the alternative hypothesis.
  • z is the test statistic. If the null hypothesis is true, it should be close to 0.
  • p is the probability that the difference between the two proportions would occur if the null hypothesis is true. When the value is sufficiently small, we reject the null hypothesis and conclude that the alternative hypothesis is true. You should have a cutoff value ready, such as 5% or 1%. If p is lower, you "reject the null hypothesis on a 5% (or 1%) level" in technical terms.
  • p-hat1 is the sample proportion x1/n1.
  • p-hat2 is the sample proportion x2/n2.
  • p-hat is the total sample proportion
  • n1 is the first sample size.
  • n2 is the second sample size.

Advanced Uses

The final optional argument of 2-PropZTest, draw?, will display the results in a graphical manner if you put in "1" for it. The calculator will draw the standard normal distribution, and shade the area of the graph that corresponds to the probability p. In addition, the value of z and the value of p will be displayed. You would make your conclusions in the same way as for the regular output.

Optimization

Some of the arguments of the 2-PropZTest command have default values, and the argument can be omitted if this value is used.

  • The draw? argument can be omitted if you don't want graphical output, although you could put "0" in as well.
  • If the above argument is omitted, and you're doing a two sided test, you may omit the alternative argument.

Example:

:2-PropZTest(22,50,48,100,0,0
can be
:2-PropZTest(22,50,48,100

Related Commands

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


The 2-SampFTest Command
2-SAMPFTEST.GIF

Command Summary

Performs a F-test to compare the standard deviations of two populations.

Command Syntax

2-SampFTest [list1, list2, frequency1, frequency2, alternative,draw?]
(data list input)

2-SampFTest s1, n1, s2, n2, [alternative,draw?]
(summary stats input)

Menu Location

While editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. ALPHA D to select 2-SampFTest, or use arrows

Outside the program editor, this will select the 2-SampFTest… interactive solver.

Change the last keypress to ALPHA E on a TI-84+/SE with OS 2.30 or higher.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

2-SampFTest performs an F-test to compare the standard deviations of two populations. This test is valid for two normally distributed populations, but is extremely sensitive to non-normality, so it should not be used unless you are certain that the populations are normal.

The logic behind the test is as follows: we want to test the hypothesis that the standard deviations of the two populations are equal (the null hypothesis). The letter σ is used for a standard deviation, so this is usually written as σ12. To do this, we assume that this "null hypothesis" is true, and calculate the probability that the difference between the two standard deviations occurred, under this assumption. If this probability is sufficiently low (usually, 5% is the cutoff point), we conclude that since it's so unlikely that the data could have occurred under the null hypothesis, the null hypothesis must be false, and therefore the deviations are not equal. If, on the other hand, the probability is not too low, we conclude that the data may well have occurred under the null hypothesis, and therefore there's no reason to reject it.

In addition to the null hypothesis, we must have an alternative hypothesis as well - usually this is simply that the two standard deviations are not equal. However, in certain cases when we have reason to suspect that one deviation is greater than the other (such as when we are trying to verify a claim that one standard deviation is greater), our alternative hypothesis may be that the first standard deviation is greater than the second (σ12) or less (σ12).

As for the 2-SampFTest command itself, there are two ways of calling it: you may give it a list of all the sample data, or the necessary statistics about the list (s1 and s2 the sample standard deviations, and n1 and n2 the sample sizes). In either case, you can indicate what the alternate hypothesis is, by a value of 0, -1, or 1 for the alternative argument. 0 indicates a two-sided hypothesis of σ1σ2, -1 indicates σ1<σ2, and 1 indicates μ1>μ2. (In fact, the calculator will treat any negative value as -1, and any positive value as 1).

Although you can access the 2-SampFTest command on the home screen, via the catalog, there's no need: the 2-SampFTest… interactive solver, found in the statistics menu, is much more intuitive to use - you don't have to memorize the syntax.

In either case, it's important to understand the output of 2-SampFTest. Here are the meanings of each line:

  • The first line, involving σ1 and σ2, is the alternative hypothesis.
  • F is the test statistic, the ratio of the standard deviations. If the null hypothesis is true, it should be close to 1.
  • p is the probability that the difference between σ1 and σ2 (the two standard deviations) would occur if the null hypothesis is true. When the value is sufficiently small, we reject the null hypothesis and conclude that the alternative hypothesis is true. You should have a cutoff value ready, such as 5% or 1%. If p is lower, you "reject the null hypothesis on a 5% (or 1%) level" in technical terms.
  • Sx1 and Sx2 are the two sample standard deviations.
  • x-bar1 and x-bar2 are the two sample means. They aren't used in the calculation, and will only be shown with the data list syntax.
  • n1 and n2 are the sample sizes.

Advanced Uses

The final optional argument of 2-SampFTest, draw?, will display the results in a graphical manner if you put in "1" for it. The calculator will draw the distribution, and shade the area of the graph that corresponds to the probability p. In addition, the value of F and the value of p will be displayed. You would make your conclusions in the same way as for the regular output.

As with most other statistical commands, you may use frequency lists in your input (when using the data list syntax). If you do, then both lists must have frequencies, and the order of the arguments would be list1, list2, frequency1, frequency2.

Optimization

Some of the arguments of the 2-SampFTest command have default values, and the argument can be omitted if this value is accepted.

  • The draw? argument can be omitted if you don't want graphical output, although you could put "0" in as well.
  • If the above argument is omitted, and you're doing a two sided test, you may omit the alternative argument.
  • With data list input, you can always omit the frequency lists if you won't be using them.
  • With data list input, if the flags that go at the end are omitted, and you're using the default lists L1 and L2, you may omit those as well.

Example:

:2-SampFTest L1,L2,0
can be
:2-SampFTest

Related Commands

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


The 2-SampTInt Command
2-SAMPTINT.GIF

Command Summary

Using either already-calculated statistics, or two data sets, computes a T confidence interval for the difference between two sample means.

Command Syntax

2-SampTInt list1, list2, [frequency1], [frequency2], [confidence level, pooled]
(data list input)

2-SampTInt x1, s1, n1, x2, s2, n2, [confidence level, pooled]
(summary stats input)

Menu Location

When editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. 0 to select 2-SampTInt, or use arrows

(this key sequence will give you the 2-SampTInt… screen outside a program)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The 2-SampTInt command uses the techniques of T Intervals to compute an interval for the difference between the means of two independent populations, at a specified confidence level. Use 2-SampTInt( when you have two independent variables to compare, and you don't know their standard deviations. The 2-SampTInt command assumes that both your variables are normally distributed, but it will work for other distributions if the sample size is large enough.

There are two ways to call this command: by supplying it with needed sample statistics (mean, standard deviation, and sample size, for both data sets), or by entering two lists and letting the calculator work the statistics out. In either case, you will need to enter the desired confidence level as well.

In the summary stats syntax, x1 and x2 the two sample means, s1 and s2 are the two sample standard deviations, and n1 and n2 the two sample sizes.

The output will contain an open interval (a, b) that is your answer: the difference between the two means will lie in this interval. Specifically, it is the second mean subtracted from the first - μ12. If you're interested in the reverse difference, just flip the signs on the interval.

Tip: don't use this command in a matched-pairs setting when you can match the two samples up by units or subjects. Instead, take the difference between the two samples in each matched pair, and use a regular TInterval.

Sample Problem

You want to compare the average height of a freshman and a senior at your school. You haven't asked everyone, but you took a random sample of 40 people from each class and found out their heights (and stored them to L1 and L2). You've decided to use a 95% confidence interval.

Based on the data list syntax for a 2-SampTInt, here is your code:

:2-SampTInt L1,L2,95
you can also use
:2-SampTInt L1,L2,.95

Alternatively, you could calculate the mean and sample size and enter those instead. The sample size in this case is 40 for both data sets; let's say the means were 57 inches and 67 inches and the standard deviations 5.2 and 7.1 inches. You now have all the needed statistics:

  • x1 is the mean height of freshmen: 57 inches
  • s1 is the sample standard deviation for freshmen: 5.2 inches
  • n1 is the number of freshmen in the sample: 40
  • x2 is the mean height of seniors: 67 inches
  • s2 is the sample standard deviation for seniors: 7.1 inches
  • n2 is the number of seniors in the sample: 40

This means that the code is:

:2-SampTInt 57,5.2,40,67,7.1,40,95
you can also use
:2-SampTInt 57,5.2,40,67,7.1,40,.95

Of course, the main use of the 2-SampTInt command is in a program. While you can enter the command on the home screen as well (just look in the catalog for it), it would probably be easier to select 2-SampTInt… from the STAT>TEST menu (see the sidebar), since you don't have to remember the syntax.

Advanced Uses

As with most other statistical commands, you can add frequencies to the lists (only with the data list syntax, of course); if you do, both lists must have frequencies, and the arguments go in the order first data list, second data list, first freq. list, second freq. list. Each frequency list must contain non-negative real numbers, which can't be all 0.

There is a final argument to 2-SampTInt: pooled. It can be either 0 or 1 (although any argument that isn't 0 will get treated as a 1); the default value is 0. If the value is 1, then then the variances will be pooled: that is, the calculator will assume that the variances of the two populations are equal, and use a combined form of the two standard deviations in place of each population's individual standard deviation. Set this flag if you have reason to believe that the standard deviations are equal.

Optimization

Using the data list syntax, all items are optional: the calculator will assume you want to use L1 and L2 for your data unless other lists are supplied, and that the confidence level you want is 95% unless you give another one. Using the summary stats syntax, the confidence level is also optional - again, the calculator will assume 95%. This means we can rewrite our code above in a simpler manner:

:2-SampTInt L1,L2,95
can be
:2-SampTInt
:2-SampTInt 57,5.2,40,67,7.1,40,95
can be
:2-SampTInt 57,5.2,40,67,7.1,40

Related Commands

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


The 2-SampTTest Command
2-SAMPTTEST.GIF

Command Summary

Performs a t significance test to compare the means of two populations.

Command Syntax

2-SampTTest [list1, list2, frequency1, frequency2, alternative, pooled? draw?]
(data list input)

2-SampTTest x1, s1, n1, x2, s2, n2, [alternative, pooled?, draw?]
(summary stats input)

Menu Location

While editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. 4 to select 2-SampTTest, or use arrows

(outside the program editor, this will select the 2-SampTTest… interactive solver)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

2-SampTTest performs a t significance test to compare the means of two populations. This test is valid for simple random samples from populations with unknown standard deviations. In addition, either the populations must be normally distributed, or the sample sizes have to be sufficiently large (usually, greater than 10).

The logic behind the test is as follows: we want to test the hypothesis that the true means of the two populations are equal (the null hypothesis). The letter μ is used for a population mean, so this is usually written as μ12. To do this, we assume that this "null hypothesis" is true, and calculate the probability that the difference between the two means occurred, under this assumption. If this probability is sufficiently low (usually, 5% is the cutoff point), we conclude that since it's so unlikely that the data could have occurred under the null hypothesis, the null hypothesis must be false, and therefore the means are not equal. If, on the other hand, the probability is not too low, we conclude that the data may well have occurred under the null hypothesis, and therefore there's no reason to reject it.

In addition to the null hypothesis, we must have an alternative hypothesis as well - usually this is simply that the two means are not equal. However, in certain cases when we have reason to suspect that one mean is greater than the other (such as when we are trying to verify a claim that one mean is greater), our alternative hypothesis may be that the first mean is greater than the second (μ12) or less (μ12).

As for the 2-SampTTest command itself, there are two ways of calling it: you may give it a list of all the sample data, or the necessary statistics about the list (x1 and x2 are the sample means, s1 and s2 the sample standard deviations, and n1 and n2 the sample sizes). In either case, you can indicate what the alternate hypothesis is, by a value of 0, -1, or 1 for the alternative argument. 0 indicates a two-sided hypothesis of μ1μ2, -1 indicates μ1<μ2, and 1 indicates μ1>μ2. (In fact, the calculator will treat any negative value as -1, and any positive value as 1).

Although you can access the 2-SampTTest command on the home screen, via the catalog, there's no need: the 2-SampTTest… interactive solver, found in the statistics menu, is much more intuitive to use - you don't have to memorize the syntax.

In either case, it's important to understand the output of 2-SampTTest. Here are the meanings of each line:

  • The first line, involving μ1 and μ2, is the alternative hypothesis.
  • t is the test statistic, the standardized difference between the means. If the null hypothesis is true, it should be close to 0.
  • p is the probability that the difference between μ1 and μ2 (the two means) would occur if the null hypothesis is true. When the value is sufficiently small, we reject the null hypothesis and conclude that the alternative hypothesis is true. You should have a cutoff value ready, such as 5% or 1%. If p is lower, you "reject the null hypothesis on a 5% (or 1%) level" in technical terms.
  • x-bar1 and x-bar2 are the two sample means.
  • Sx1 and Sx2 are the two sample standard deviations.
  • n1 and n2 are the sample sizes.

Sample Problem

Your school claims that the average SAT score of students at the school is higher than at a rival school. You took samples of SAT scores from students at both schools (and stored them to L1 and L2).
Since the school's claim is that your school's score is higher, that will be your alternative hypothesis (μ1>μ2), which corresponds to a value of 1. The code you'd use is:

:2-SampTTest L1,L2,1

Alternatively, you could calculate the mean, standard deviation, and size of your samples, and put those into the command instead. Suppose you obtained SAT scores from 60 students at your school and 40 students at the rival school, the means were 1737 and 1623, and the standard deviation 211 and 218. Then your code is:

:2-SampTTest 1737,211,60,1623,218,40,1

You will see the following output:

2-SampTTest
 μ1>μ2
 z=2.594854858
 p=.0056059824
 x1=1737
 x2=1623
 Sx1=211
 Sx2=218
 n1=60
 n2=40

The most important part of this output is "p=.0056059824". This value of p is smaller than 1% or 0.01. This is significant on the 1% level, so we reject the null hypothesis and conclude that the alternative hypothesis is true: μ12, that is, your school's average SAT score is indeed higher.

Advanced Uses

The final optional argument of 2-SampTTest, draw?, will display the results in a graphical manner if you put in "1" for it. The calculator will draw the distribution, and shade the area of the graph beyound the t statistic. In addition, the value of t and the value of p will be displayed (the value of p corresponds to the shaded area). You would make your conclusions in the same way as for the regular output.

The optional argument pooled?, if given a nonzero value, will pool the standard deviations to find a combined value which will then be used for both populations. Use this feature if you have reason to believe that the two populations have the same standard deviation.

As with most other statistical commands, you may use a frequency list in your input (when using the data list syntax). If you do, then both lists must have frequencies, and the order of the arguments would be list1, list2, frequency1, frequency2.

Optimization

Some of the arguments of the 2-SampTTest command have default values, and the argument can be omitted if this value is accepted.

  • The draw? argument can be omitted if you don't want graphical output, although you could put "0" in as well.
  • If the draw? argument is omitted, you can omit the pooled? argument if you do not want your standard deviations pooled.
  • If both the above arguments are omitted, and you're doing a two sided test, you may omit the alternative argument.
  • With data list input, you can always omit the frequency lists if you won't be using them.
  • With data list input, if the flags that go at the end are omitted, and you're using the default lists L1 and L2, you may omit those as well.

The code in the sample problem above can't be optimized, because the alternative argument is 1:

:2-SampTTest L1,L2,1

However, if we were doing a two-sided test, we could omit the alternative argument as well as the lists:

:2-SampTTest L1,L2,0
can be just
:2-SampTTest

Related Commands

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


The 2-SampZInt( Command
2-SAMPZINT.GIF

Command Summary

Using either already-calculated statistics, or two data sets, computes a Z confidence interval for the difference between two sample means.

Command Syntax

2-SampZInt(σ1, σ2, [list1, list2, [frequency1], [frequency2], [confidence level]
(data list input)

2-SampZInt(σ1, σ2, x1, n1, x2, n2, level//
(summary stats input)

Menu Location

When editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. 9 to select 2-SampZInt(, or use arrows

(this key sequence will give you the 2-SampZInt… screen outside a program)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The 2-SampZInt( command uses the techniques of Z Intervals to compute an interval for the difference between the means of two independent populations, at a specified confidence level. Use 2-SampZInt( when you have two independent variables to compare, and you already know their standard deviations. The 2-SampZInt( command assumes that both variables are distributed normally, but it will work for other distributions if the sample size is large enough.

There are two ways to call this command: by supplying it with needed sample statistics (mean and sample size, for both data sets), or by entering two lists and letting the calculator work the statistics out. In either case, you will need to enter the standard deviation and desired confidence level as well.

In the data list syntax, σ1 and σ2 are the two standard deviations.
In the summary stats syntax, σ1 and σ2 are the two standard deviations, x1 and x2 the two sample means, and n1 and n2 the two sample sizes.

The output will contain an open interval (a, b) that is your answer: the difference between the two means will lie in this interval. Specifically, it is the second mean subtracted from the first - μ12. If you're interested in the reverse difference, just flip the signs on the interval.

Tip: don't use this command in a matched-pairs setting when you can match the two samples up by units or subjects. Instead, take the difference between the two samples in each matched pair, and use a regular ZInterval.

Sample Problem

You want to compare the average height of a freshman and a senior at your school. You haven't asked everyone, but you took a random sample of 40 people from each class and found out their heights (and stored them to L1 and L2). You've read in your textbook that the standard deviation of teenagers' heights is usually 6 inches. You've decided to use a 95% confidence interval.

Based on the data list syntax for a 2-SampZInt(, here is your code:

:2-SampZInt(6,6,L1,L2,95
you can also use
:2-SampZInt(6,6,L1,L2,.95

Alternatively, you could calculate the mean and sample size and enter those instead. The sample size in this case is 40 for both data sets; let's say the means were 57 inches and 67 inches. You now have all the needed statistics:

  • σ1 is the standard deviation for freshmen: 6 inches
  • σ2 is the standard deviation for seniors: also 6 inches
  • x1 is the mean height of freshmen: 57 inches
  • n1 is the number of freshmen in the sample: 40
  • x2 is the mean height of seniors: 67 inches
  • n2 is the number of seniors in the sample: 40

This means that the code is:

:2-SampZInt(6,6,57,40,67,40,95
you can also use
:2-SampZInt(6,6,57,40,67,40,.95

Of course, the main use of the 2-SampZInt( command is in a program. While you can enter the command on the home screen as well (just look in the catalog for it), it would probably be easier to select 2-SampZInt… from the STAT>TEST menu (see the sidebar), since you don't have to remember the syntax.

Advanced Uses

As with most other statistical commands, you can add frequencies to the lists (only with the data list syntax, of course); if you do, both lists must have frequencies, and the arguments go in the order first data list, second data list, first freq. list, second freq. list. Each frequency list must contain non-negative real numbers, which can't be all 0.

Optimization

Using the data list syntax, all items but the standard deviations are optional: the calculator will assume you want to use L1 and L2 for your data unless other lists are supplied, and that the confidence level you want is 95% unless you give another one. Using the summary stats syntax, the confidence level is also optional - again, the calculator will assume 95%. This means we can rewrite our code above in a simpler manner:

:2-SampZInt(6,6,L1,L2,95
can be
:2-SampZInt(6,6
:2-SampZInt(6,6,57,40,67,40,95
can be
:2-SampZInt(6,6,57,40,67,40

Related Commands

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


The 2-SampZTest( Command
2-SAMPZTEST.GIF

Command Summary

Performs a z significance test to compare the means of two populations.

Command Syntax

2-SampZTest(σ1, σ2 //list2//, //frequency1//, //frequency2//, //alternative//, //draw?//
(data list input)

2-SampZTest(σ1, σ2 x1, n1, x2, n2, //draw?//
(summary stats input)

Menu Location

While editing a program, press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. 3 to select 2-SampZTest(, or use arrows

(outside the program editor, this will select the 2-SampZTest… interactive solver)

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

2-SampZTest( performs a z significance test to compare the means of two populations. This test is valid for simple random samples from populations with known standard deviations. In addition, either the populations must be normally distributed, or the sample sizes have to be sufficiently large (usually, greater than 10).

The logic behind the test is as follows: we want to test the hypothesis that the true means of the two populations are equal (the null hypothesis). The letter μ is used for a population mean, so this is usually written as μ12. To do this, we assume that this "null hypothesis" is true, and calculate the probability that the difference between the two means occurred, under this assumption. If this probability is sufficiently low (usually, 5% is the cutoff point), we conclude that since it's so unlikely that the data could have occurred under the null hypothesis, the null hypothesis must be false, and therefore the means are not equal. If, on the other hand, the probability is not too low, we conclude that the data may well have occurred under the null hypothesis, and therefore there's no reason to reject it.

In addition to the null hypothesis, we must have an alternative hypothesis as well - usually this is simply that the two means are not equal. However, in certain cases when we have reason to suspect that one mean is greater than the other (such as when we are trying to verify a claim that one mean is greater), our alternative hypothesis may be that the first mean is greater than the second (μ12) or less (μ12).

As for the 2-SampZTest( command itself, there are two ways of calling it: after giving the two standard deviations, you may give it a list of all the sample data, or the necessary statistics about the list (x1 and x2 are the sample means, and n1 and n2 are the sample sizes). In either case, you can indicate what the alternate hypothesis is, by a value of 0, -1, or 1 for the alternative argument. 0 indicates a two-sided hypothesis of μ1μ2, -1 indicates μ1<μ2, and 1 indicates μ1>μ2. (In fact, the calculator will treat any negative value as -1, and any positive value as 1).

Although you can access the 2-SampZTest( command on the home screen, via the catalog, there's no need: the 2-SampZTest… interactive solver, found in the statistics menu, is much more intuitive to use - you don't have to memorize the syntax.

In either case, it's important to understand the output of 2-SampZTest. Here are the meanings of each line:

  • The first line, involving μ1 and μ2, is the alternative hypothesis.
  • z is the test statistic, the standardized difference between the means. If the null hypothesis is true, it should be close to 0.
  • p is the probability that the difference between μ1 and μ2 (the two means) would occur if the null hypothesis is true. When the value is sufficiently small, we reject the null hypothesis and conclude that the alternative hypothesis is true. You should have a cutoff value ready, such as 5% or 1%. If p is lower, you "reject the null hypothesis on a 5% (or 1%) level" in technical terms.
  • x-bar1 and x-bar2 are the two sample means.
  • n1 and n2 are the sample sizes.

Sample Problem

Your school claims that the average SAT score of students at the school is higher than at a rival school. You took samples of SAT scores from students at both schools (and stored them to L1 and L2). Although you didn't know the standard deviations, you decided to use the value 200 that you found online as an estimate.

You now have all the data. You're assuming σ1 and σ2 are both 200; the two data lists are L1 and L2. Since the school's claim is that your school's score is higher, that will be your alternative hypothesis (μ1>μ2), which corresponds to a value of 1. The code you'd use is:

:2-SampZTest(200,200,L1,L2,1

Alternatively, you could calculate the mean and sample size of your sample, and put those into the command instead. Suppose you obtained SAT scores from 60 students at your school and 40 students at the rival school, and that the means were 1737 and 1623. Then your code is:

:2-SampZTest(200,200,1737,60,1623,40,1

You will see the following output:

Z-Test
 μ1>μ2
 z=2.792418307
 p=.0026158434
 x1=1737
 x2=1623
 n1=60
 n2=40

The most important part of this output is "p=.0026158434". This value of p is much smaller than 1% or 0.01. This is significant on the 1% level, so we reject the null hypothesis and conclude that the alternative hypothesis is true: μ12, that is, your school's average SAT score is indeed higher.

Advanced Uses

The final argument of 2-SampZTest(, draw?, will display the results in a graphical manner if you put in "1" for it. The calculator will draw the standard normal curve, and shade the area of the graph beyond the z statistic. In addition, the value of z and the value of p will be displayed (the value of p corresponds to the shaded area). You would make your conclusions in the same way as for the regular output.

As with most other statistical commands, you may use a frequency list in your input (when using the data list syntax). If you do, then both lists must have frequencies, and the order of the arguments would be list1, list2, frequency1, frequency2.

Optimization

Most of the arguments of the 2-SampZTest( command have default values, and the argument can be omitted if this value is accepted.

  • The draw? argument can be omitted if you don't want graphical output, although you could put "0" in as well.
  • If the draw? argument is omitted, you can omit the alternative argument to use a two-sided test (μ1μ2). If you include the draw? argument, you have to include this - otherwise there will be confusion as to what the 5th argument means.
  • With data list input, you can always omit the frequency lists if you won't be using them.
  • With data list input, if the draw? and alternative arguments are omitted, and your data is in L1 and L2 (and you're not using frequency lists), you may omit L1 and L2 - those are default parameters. However, if alternative or draw? is present, you have to include it, or else the syntax may be confused with the syntax for summary stats input.

The code in the sample problem above can't be optimized, because the alternative argument is 1:

:2-SampZTest(200,200,L1,L2,1

However, if we were doing a two-sided test, we could omit the alternative argument as well as the lists:

:2-SampZTest(200,200,L1,L2,0
can be
:2-SampZTest(200,200

Related Commands

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


The 2-Var Stats Command
2-VARSTATS.GIF

Command Summary

Calculates some common statistics for two lists of data, and stores them to statistical variables. They're also displayed in a scrollable list, if done outside a program.

Command Syntax

2-Var Stats [list1, list2, [freqlist]]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the CALC submenu
  3. 2 to select 2-Var Stats, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

This command calculates a bunch of common (and a few uncommon) statistics for a pair of lists (it uses L1 and L2 by default, but you can use any list by supplying it as an argument). You have to store the lists to variables first, though, before calculating statistics for them. For example:

:{5,12,7,8,4,9→L1
:{1,0,2,5,7,4→L2
:2-Var Stats

The calculator treats the two lists as a list of ordered pairs. Some of the statistics calculated assume that this is the case, and the two lists are the same size: an error will occur if the lists don't match.

Like other statistical commands, you can use a frequency list as well, for cases where one element occurs more times than another (you can do this with a normal list, too, but that might be inconvenient when an element occurs very many times). There is only one frequency list for both data lists, and the frequency applies to the ordered pair formed by an element taken from each list. For example:

:{1,2,3→L1
:{1,2,3→L2
:{5,3,2→L3
:2-Var Stats L1,L2,L3

is the frequency-list equivalent of:
:{1,1,1,1,1,2,2,2,3,3→L1
:{1,1,1,1,1,2,2,2,3,3→L2
:2-Var Stats

When you're running it from the home screen, 2-Var Stats will display the statistics; this won't happen if you do it inside a program. Either way, it will also store what it calculated to the statistics variables found in VARS>Statistics… The variables 2-Var Stats affects are:

  • $\definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} \overline{\textrm{x}}$ is the mean (average) of the first list
  • Σx is the sum of the first list
  • Σx² is the sum of the squares of the first list
  • Sx is the sample standard deviation of the first list
  • σx is population standard deviation of the first list
  • minX is the minimum element of the first list
  • maxX is the maximum element of the first list
  • $\definecolor{darkgreen}{rgb}{0.90,0.91,0.859}\pagecolor{darkgreen} \overline{\textrm{y}}$ is the mean (average) of the second list
  • Σy is the sum of the second list
  • Σy² is the sum of the squares of the second list
  • Sy is the sample standard deviation of the second list
  • σy is population standard deviation of the second list
  • minY is the minimum element of the second list
  • maxY is the maximum element of the second list
  • Σxy is the sum of products of each matching pair of elements in the lists
  • n is the number of elements in both lists

2-Var Stats will not work with "reserved" list names that the calculator uses internally. The only known such reserved list is the list RESID, and there's no reason to suspect there are any others. Ans, TblInput, and any expression which resolves to a list, are also not appropriate for this command: store all of these to a list before doing 2-Var Stats on them.

Advanced uses

If you consider the two lists to be vectors, then Σxy is their dot product, and Σx² and Σy² are the squares of their norms; math done with these and other statistics can produce the shortest (but not necessarily quickest) way to calculate many vector operations.

Optimization

Aside from statistical analysis, 2-Var Stats can also be used when you want to use the values it calculates more than once. This will save on size, since, for example Σx takes up less space than sum(L1), but considering how many calculations 2-Var Stats makes, it will usually be slower.

Related Commands

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


The ³ Command
CUBE.GIF

Command Summary

Raises the input to the third power.

Command Syntax

value³

Menu Location

While editing a program, press:

  1. MATH to enter the MATH menu
  2. 3 or use the arrow keys to select.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ³ command raises an input to the third power. It has exactly the same function as "^3", but is one byte smaller. If used on a list, it will return a list with all of the elements cubed. If used on a matrix, it will return the third matrix power of the input matrix.

2³
        8
{1,‾2,3}³
        {1 ‾8 27}
[[2,‾1][‾3,0]]³
        [[20  ‾7]
         [‾21  6]]

Advanced Uses

One trick with ³ is to use it to save space (at the cost of speed) when using hard-coded values. For instance, use 5³ instead of 125 to save one byte.

Optimization

Use this command instead of ^3 in all instances.

:X^3
can be
:X³

Related Commands

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


The ³√( Command
CUBEROOT.GIF

Command Summary

Take the cube root of a number.

Command Syntax

³√(input)

Menu Location

While editing a program, press:

  1. MATH to open the math menu
  2. 4 or use the arrow keys to select.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

Takes the cube root of a positive or negative number. It works exactly the same as 3×√ or ^(1/3) but is smaller and uses an ending parenthesis. If used on a list, it will return a list with the cube root of each element.

³√(8)
        2
³√(2)
        1.25992105

³√({1,‾8,27})
        {1 ‾2 3}

For complex numbers, the principal cube root is returned, which may be different from the cube root you'd get for the same real number:

³√(-8)
        -2
³√(-8+0i)
        1+1.732050808i

Optimization

Never raise something to the one-third power explicitly; use this command instead.

:X^(1/3)→X
can be
:³√(X→X

Related Commands

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


The a+bi Command
APLUSBI.GIF

Command Summary

Puts the calculator into a+bi mode.

Command Syntax

a+bi

Menu Location

Press:

  1. MODE to access the mode menu.
  2. Use the arrow keys and ENTER to select a+bi

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The a+bi command puts the calculator into rectangular 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 a+bi (hence the name of the command)

This is the standard way of displaying complex numbers, though they can also be displayed in polar form (see re^θi for more details). To extract the coefficients a and b, use the real( and imag( commands.

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/a-bi


The abs( Command
ABS.GIF

Command Summary

Returns the absolute value of a real number, and the complex absolute value of a complex number.

Command Syntax

abs(value)

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT to access the NUM submenu.
  3. ENTER to select abs(.

Alternatively, press:

  1. MATH to access the math menu.
  2. RIGHT twice to access the CPX (complex) submenu.
  3. 5 to select abs(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

abs(x) returns the absolute value of the real number x. Also works on a list or matrix of real numbers.

abs(3)
     3

abs(‾3)
     3

For complex numbers, abs(z) returns the absolute value (also known as the complex modulus, norm, or a hundred other terms) of the complex number z. If z is represented as x+iy where x and y are both real, abs(z) returns √(x²+y²). Also works on a list of complex numbers.

abs(3+4i)
     5

Optimization

The abs( command, used properly, may be a smaller method of testing if a variable is in some range. For example:

:If 10<X and X<20
can be
:If 5>abs(X-15

In general, the first number, A, in the expression A>abs(X-B) should be half the length of the range, half of 10 in this case, and the second number, B, should be the midpoint of the range (here, 15).

This can be taken to extreme degrees. For example, the following code uses abs( three times to test if X is the getKey keycode of one of the keys 1, 2, 3, 4, 5, 6, 7, 8, or 9:

:If 2>abs(5-abs(5-abs(X-83

For complex numbers given by a separate real and complex part, abs(X+iY) can be optimized to R►Pr(X,Y).

Related Commands

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


The and Command
AND.GIF

Command Summary

Returns the logical value of value1 and value2 being true.

Command Syntax

value1 and value2

Menu Location

Press:

  1. 2nd TEST to access the test menu.
  2. RIGHT to access the LOGIC submenu.
  3. ENTER to select and.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

and takes two numbers, variables, or expressions and tests to see if they are both True (not equal to 0). If they are, it returns 1. If either input is False (0), it returns 0. Note that the order of the operators doesn't matter (i.e. and is commutative), and that multiple and's can be used together

:0 and 0 
           0

:0 and 1
           0 

:1 and 2           (2 counts as True, just like one)
           1

:1→X
:X and 2+2         (you can use variables and expressions)
           1

:1 and 1 and 2-2   (the last input evaluates to 0, or false)
           0

Optimization

Multiplying two values has the same truth value as and; thus, and can sometimes be replaced by multiplication. Because the calculator does implicit multiplication, meaning it automatically recognises when you want to multiply, you don't need to use the * sign.

:If A and B
can be
:If AB

However, do not use this optimization if A and B might be expected to take on large values, as an overflow error might occur.

Related Commands

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


The and Command

and.png

Command Summary

Tests if two conditions are both true.
Can also be used as a bitwise "and" on integers.

Command Syntax

condition1 and condition2
integer1 and integer2

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 8 to enter the Test submenu.
  • Press 8 to select and.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The and operator combines two conditions into one, which will be true if both sides are true, and false otherwise. 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 or, xor, and not.

:2+2=4 and 1=0
           false
:2+2=4 and 1+1=2
           true

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 "and" will be applied to the bits individually — a bit in the result will be 1 if the two corresponding bits of the original integers were 1, and 0 otherwise.

:(0b11111100 and 0b00111111)▶Bin
           0b111100
:1000 and 512
           512

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:and


The AndPic Command

andpic.png

Command Summary

Logically "ands" a picture variable and the graph screen at [row, column]

Command Syntax

AndPic 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.

The AndPic command logically takes the picture variable specified, and takes the current graph, and it finds the points at which both the graph and the picture have pixels, and it displays them only. If specified, [row,column] tells where the top left corner of the picture is to be placed. If not specified, the default is (0,0), which is the top left corner of the screen.

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:andpic


The angle( Command
ANGLE.GIF

Command Summary

Returns the complex argument of a complex number.

Command Syntax

angle(z)

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT, RIGHT to access the CPX (complex) submenu
  3. 4 to select angle(, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

angle(z) returns the complex argument (also known as the polar angle) of the complex number z. If z is represented as x+iy where x and y are both real, angle(z) returns R►Pθ(x,y) (which is equivalent to tanֿ¹(y/x) if x is nonzero). Also works on a list of complex numbers.

angle(3+4i)
     .927295218
R►Pθ(3,4)
     .927295218

When writing a complex number z in the form $re^{i\theta}$ (or, equivalently, $r(\cos\theta+i\sin\theta)$), then $\theta$ is equal to the value of angle(z), suitably reduced so that the result returned is in the interval $-\pi<\theta\leq\pi$.

The angle( command also works on matrices, though not in any useful way: angle([A] will return a matrix of the same size as [A], but with all elements 0. If you plan to use this, don't: 0[A] does the same thing, but is smaller and not as questionable (because this behavior is clearly unintentional on TI's part, and may be changed in an OS update).

Related Commands

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


The ANOVA( Command
ANOVA.GIF

Command Summary

Performs a one way ANOVA (analysis of variance) test to compare the means of multiple populations (up to 20).

Command Syntax

ANOVA(list, list, …

Menu Location

Press:

  1. STAT to access the statistics menu
  2. LEFT to access the TESTS submenu
  3. ALPHA F to select ANOVA(, or use arrows

Change the last keypress to ALPHA H on a TI-84+/SE with OS 2.30 or higher.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The ANOVA (analysis of variance) command is used to test if there is a significant difference between the means of several populations (this is an extension of the two-sample t-test which compares only two populations). The calculator assumes the null hypothesis, that all means are equal, and returns a probability value, p, of the differences in the data occurring if the null hypothesis were true. If p is small (usually, if it's less than .05), then it's unlikely we'd get such differences just by chance if the null hypothesis were true, so we reject it and conclude that at least one of the means is different.

There are two reasons why we don't test the means in pairs using a simpler test. First of all, it would take a long time: there's so many pairs to compare. Second of all, when you're doing many tests, there's a high probability you'll get a low p-value by chance. Imagine that you're doing 10 tests. If the probability of getting a low p-value on one test is .05, then the probability that at least one test will return one is 1-.9510: about 0.4 - this is quite likely to happen. The ANOVA test avoids this by having only one null hypothesis to test.

If you're only interested in the result of the test, the only thing you'll need in the output is the second line: "p=…" This is your p-value, and determines whether you should reject the null hypothesis or not. If you need more detail, here are the meanings of the other variables:

  • F is the test statistic. If the null hypothesis is true, it should follow Snedecor's F distribution, and Fcdf( can be used to determine the p-value.
  • For both Factor and Error:
    • MS is the mean squares (SS/df). If the null hypothesis is true, Factor MS should be roughly equal to Error MS
    • SS is the sum of squares - see the TI-83+ Manual for formulas
    • df is the number of degrees of freedom - for Factor, it's the df between the categorical variables, and for Error, it's the sum of df between each variable.
  • Sxp is the pooled variation.

Advanced Uses

The statistics F, p, and Sxp will be stored to the appropriate variables after this test. The other six statistics do not have a normal variable associated with them. However, the two-byte tokens 0x6237 through 0x623C are, in fact, used to store the values of Factor MS, Factor SS, Factor df, Error MS, Error SS, and Error df respectively. They can't be accessed through a menu, but if you use a hex editor to paste them into your program, you will be able to use them just like any other variable.

However, be careful because the Factor and Error tokens look exactly alike (even though they refer to different variables), and can be confused. Also, there is a chance that future OS versions will change the behavior of ANOVA(, though this is unlikely, and this trick will no longer work.

Error Conditions

  • ERR:ARGUMENT is thrown if one of the lists is blank, only one list is used, or the function is completely blank.
  • ERR:SYNTAX is thrown if you do not use lists (Matrixes, numbers,etc)
  • * ERR:INVALID DIM is thrown if you use a list that has 0 or a negative number.
  • * ERR:DATA TYPE is thrown by using "l" or a list with a different set of data.

Related Commands

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


The Ans Variable
ANS.GIF

Command Summary

Returns the last answer.

Command Syntax

Ans[→Variable]

Menu Location

While editing a program, press [2nd] then [(-)]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The Ans variable holds the last answer that was stored in the calculator. Because Ans is stored in a special storage area built-in to the calculator, and it is extensively used by the calculator, you cannot delete it. Ans is also useful; it can make your programs both smaller and faster:

  • Unlike other variables which have a value type hard-coded in (i.e., a string can only hold text, and lists and matrices can only hold numbers), Ans can take on whatever value you want: a real or complex, list, matrix, or string are all acceptable.
  • Along with the finance variables, Ans is faster than the real, complex, list, matrix, and string variables; and subsequently, you should try to use it as much as possible.

One of the most common places to use Ans is in place of storing a value to a variable. Just paste the Ans variable to the location where the variable was called, and then when the expression is evaluated, the calculator will use the current value of Ans. Using the Ans variable allows you to eliminate the variable, which helps save a little or a lot of memory (depending on the type of variable and its size).

30+5A→B
Disp 25A,30+5A
;can be
30+5A
Disp 25A,Ans

The one major drawback to using Ans is that its current value is only temporary. Whenever you store a value to a variable, place an expression or string on a line by itself, or use the optional argument of the Pause command, Ans is updated to the new value. This restriction essentially limits your use of Ans to only a single variable. If you are manipulating two or more variables, it's best to just use the variables.

There are several cases in which changing the value of a variable does not modify Ans, thus preserving its current value for later use:

  • storing to an equation variable
  • using the DelVar command to delete a variable (i.e., set its value to zero, if it's a real variable)
  • changing the value with IS>( or DS<(.
  • initializing or changing the value in a For( loop.

These cases can be very useful, allowing you to use Ans to store an expression rather than create a temporary variable for it.

Timing

Storing a real value into Ans takes approximately 1.0 ms. This does not include the time needed to compute or retrieve the value, which may be significant.

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


The approx() Command

approx.png

Command Summary

Gives a decimal approximation of an expression.

Command Syntax

approx(expression)

Menu Location

While on the home screen:

  • Press F2 to enter the Algebra menu.
  • Press 5 to paste approx(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The approx() command forces an expression to be evaluated in approximate mode, temporarily ignoring the mode setting. It's equivalent to pressing ♦ and ENTER when performing a calculation on the home screen.

:approx(π)
           3.14159265359

When applied to a complicated expression, matrix, or list, it approximates every number that occurs there.

Related Commands

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


The Archive Command
ARCHIVE.GIF

Command Summary

Moves a variable from RAM to the archive.

Command Syntax

Archive variable

Menu Location

Press:

  1. 2nd MEM to access the memory menu
  2. 5 to select Archive, or use arrows

Calculator Compatibility

TI-83+/84+/SE

(not available on the regular TI-83)

Token Size

2 bytes

The Archive command moves a variable from RAM to the archive (also known as ROM). A quick synopsis of the difference between the two:

  • Data in the archive cannot be accessed, but it's protected from RAM clears (which may occur during battery removal if not done carefully); also, the archive can hold much more data.
  • Data in RAM can be accessed for calculations, but it can also be deleted during a RAM clear or accidentally overwritten by another program.

Nothing happens if the variable in question is already archived.

You might want to use this command to protect data such as saved games from being accidentally deleted. It's not, in general, a good idea to archive commonly used variables, such as the real variables A-Z, since programs usually expect to be able to access these variables without problems, and won't check if they're archived.

Also, some variables cannot be archived. These include:

  • The real variables R, T, X, Y, θ, and n (due to their use in graphing)
  • The equation variables Yn, XnT, YnT, rn, u, v, and w
  • The stat plots Plot#
  • Window, table, and zoom variables such as TblInput or Xmin
  • Statistical variables and the list ∟RESID
  • Finance variables

Finally, the Archive command does not work on programs when using it from a program (it does, however, archive programs from the home screen). However, an assembly program can be executed as a subroutine so that Archive and UnArchive can be used within a program. The program should however be run again afterwards.

Advanced Uses

As archived variables (and programs) can not be accessed by the calculator's inbuilt OS, archiving programs can be quite problematic when trying to execute them. However; by enabling your programs to be viewable in assembly shells, you can execute your programs without needing to unarchive them first. This is because the assembly shell copies the program to the RAM automatically, and is then executed. Closing the program will automatically remove the copy from the RAM, so no RAM is lost in the end.

Error Conditions

  • ERR:ARCHIVE FULL is thrown when there isn't enough space in the archive for the variable.
  • ERR:INVALID is thrown when trying to archive a program from within a program.
  • ERR:VARIABLE is thrown when trying to archive a variable that cannot be archived.

Related Commands

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


The Archive Command

archive.png

Command Summary

Moves a variable from RAM to the archive.

Command Syntax

Archive variable, [another, …]

Menu Location

Starting in the program editor:

  • Press F4 to enter the Var menu.
  • Press 8 to select Archive.

Calculator Compatibility

This command works on all calculators.

Token Size

3 bytes

The Archive command moves a variable, or several variables, from RAM to the archive. This serves two purposes:

  • More RAM is now available for other variables.
  • The variable is protected from being edited or deleted.

On the 68k series of calculators, a variable in the archive can still be read (compare this to the behavior of TI-83 series calculators, where doing anything at all to an archived variable is forbidden). However, trying to store anything to the variable will give an error: it must be unarchived first.

Variables in the archive are also protected from being deleted. This means that a DelVar command called on it will cause an error. Commands such as NewProb or DelType that delete multiple variables will skip over any that are archived. Finally, in the event of a RAM clear (which is more likely to happen by accident than a total memory clear), archived variables will be preserved.

Any type of variable can be archived. However, you cannot archive system variables (such as xmin) or variables beginning with _.

Advanced Uses

It seems natural to archive programs, since they usually aren't written to, and they are valuable enough that you want to give them some protection. However, keep in mind that the first time you run a program after editing it, it gets tokenized — the text is converted into tokens that stand in for commands. The process might take several seconds.

If you edit a program and then immediately archive it, it is "protected" from this conversion process. That means that every time you run the program, it will be tokenized. To avoid this, run the program once to tokenize it, and then archive it.

Error Conditions

140 - Argument must be a variable name happens when archiving a system variable or an invalid variable name.

870 - Reserved name or system variable happens when archiving a variable starting with _.

960 - Undefined variable happens when archiving an undefined variable.

Related Commands

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


The arcLen() Command

arclen.png

Command Summary

Returns the arc length of expression1 from start to end with respect to variable var.

Command Syntax

arcLen(expression1,var,start,end)

Menu Location

Describe how to get the command from a menu.

Calculator Compatibility

This command works on all calculators.

Token Size

X byte(s)

The arcLen() command uses the integral arc length formula to calculate the arc length of a function over the specified interval.

arcLen(cos(x),x,0,π)
                              3.82019...

Advanced Uses

The arcLen() command also works on lists of expressions:

arcLen({sin(x),cos(x)},x,0,π)
                         {3.820...  3.810...}

Separate unrelated advanced uses with a horizontal bar.

Optimization

This section includes both ways to optimize use of the command, and other common pieces of code that this command can replace in an optimization. Make sure to mention if the optimization improves speed of the program, size, or both. Sample code should be included too, preferably in the following format:

:∫(√(1+d(f(x),x)²),x,a,b)
can be
:arcLen(f(x),x,a,b)

Related Commands

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


The Asm( Command
ASM.GIF

Command Summary

Runs an assembly program.

Command Syntax

Asm(prgmNAME)

Menu Location

This command is only found in the catalog. Press:

  1. 2nd CATALOG to access the command catalog.
  2. DOWN six times.
  3. ENTER to select Asm(.

Calculator Compatibility

TI-83+/84+/SE

(not available on the regular TI-83)

Token Size

2 bytes

The Asm( command is used for running an assembly program. Unlike TI-Basic programs, assembly programs are written in the calculator's machine code directly, which makes them more powerful in both speed and functionality. However, it also means that if they crash, they crash hard — there is no built-in error menu to protect you.

Keep in mind that many assembly programs these days are written for a shell such as Ion or MirageOS. If you're dealing with one of those programs, calling Asm( on it will do nothing; you need to get the appropriate shell and run that instead.

With the AsmPrgm and AsmComp( commands, you can create small assembly programs yourself, directly on the calculator. If you are using at TI-84+CE with OS 5.3, the Asm( is unnecessary to run such programs.

Error Conditions

  • ERR:INVALID is thrown if the program isn't an assembly program.

Related Commands

See Also

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


The AsmComp( Command
ASMCOMP.GIF

Command Summary

Compresses an assembly program in hexadecimal form into binary form.

Command Syntax

Asm(prgmORIGINAL,prgmRESULT)

Menu Location

This command is only found in the catalog. Press:

  1. 2nd CATALOG to access the command catalog.
  2. Scroll down to AsmComp( and press enter.

Calculator Compatibility

TI-83+/84+/SE/CSE/CE

(not available on the regular TI-83)

Token Size

2 bytes

This command is used to compress an assembly program written using AsmPrgm into an "assembled" assembly program. This will make the program about twice as small, and protect it from being edited, in addition to making execution faster.

To use AsmComp(, give it the ASCII represented assembly program, followed by the name you want the assembled program to have. That name can't be already taken. Since it's not easy to rename an assembled assembly program, if you want to write a program called prgmGAME, you type the ASCII represented code in a program with a different name (e.g. GAMEA) and then do AsmComp((prgmGAMEA,prgmGAME).

Assembly programs can be run with Asm(.

Error Conditions

Related Commands

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


The AsmPrgm Command
ASMPRGM.GIF

Command Summary

This command must be the beginning of an assembly program.

Command Syntax

AsmPrgm

Menu Location

This command is only found in the catalog. Press:

  1. 2nd CATALOG to access the command catalog.
  2. Scroll down to AsmPrgm and press ENTER.

Calculator Compatibility

TI-83+/84+/SE/CSE/CE

(not available on the regular TI-83)

Token Size

2 bytes

This command denotes the start of an assembly program in hexadecimal form. The command must go at the beginning of a program.

Using AsmPrgm is the only built-in way to create assembly programs on the calculator, and it's not very convenient. To use it, after AsmPrgm itself, you must type in the hexadecimal values (using the numbers 0-9, and the letters A-F) of every byte of the assembly program. Even for assembly programmers, this is a complicated process: unless you've memorized the hexadecimal value of every assembly command (which is about as easy as memorizing the hexadecimal value of every TI-Basic token) you have to look every command up in a table.

In addition, it's easy to make a typo while doing this. For this reason, it's recommended not to use AsmPrgm to write assembly programs on the calculator, but instead write assembly programs on the computer. This also lets you use emulators and debuggers and such, as opposed to crashing your calculator (possibly permanently) every time you have a bug.

Just about the only use for AsmPrgm is to enter the hex codes for simple assembly routines that can be called from Basic programs or used for some other short task. For example, the following program will allow you to type in lowercase letters (by pressing ALPHA twice, you go into lowercase letter mode):

AsmPrgmFDCB24DEC9

To use this, create a program, and enter the code above into it. Then run the program using Asm(. Voila! Lowercase letters are now enabled.

More such short programs can be found here.

TI-84+ Color Calculators

For the TI-84+ C series of calculators, AsmPrgm has been replaced by two new commands: AsmPrgm84C for the TI-84+ CSE and AsmPrgmCE for the TI-84+ CE. The commands function in the exact same manner as the original AsmPrgm command. However, it is important to note that sending assembly programs between a CSE and CE (or vice versa) may cause errors due to a difference in commands.

Many of the hex codes involving AsmPrgm also no longer function correctly on C series calculators. The updated hex codes can be found here.

Related Commands

See Also

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


The augment( Command
AUGMENT.GIF

Command Summary

Combines two lists or matrices into one. In the case of matrices, this is done horizontally rather than vertically.

Command Syntax

augment(list1,list2

augment(matrix1,matrix2

Menu Location

Press:

  1. 2nd LIST to access the List menu
  2. RIGHT to access the OPS submenu
  3. 9 to select augment(, or use arrows

Alternatively, 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. 7 to select augment(, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The augment( command is used to combine two lists or two matrices into one. For lists, this is done the obvious way: adding the elements of the second on to the elements of the first. For example:

augment({1,2,3,4},{5,6,7
    {1 2 3 4 5 6 7}

For matrices, the columns of the second matrix are added after the columns of the first matrix: an R by C matrix augmented with an R by D matrix will result in an R by (C+D) matrix. For example:

augment([[1][2]],[[3][4]
    [[1 3]
     [2 4]]

Advanced Uses

Use the T (transpose) command if you want to combine two matrices vertically, rather than horizontally. For example:

augment([[1,2]]T,[[3,4]]T)T
    [[1 2]
     [3 4]]

Optimization

You may be tempted to use augment( to add one element to the end of a list:

:augment(L1,{X→L1

However, the following way is faster and more memory-efficient while the program is running (although it increases the program's size):

:X→L1(1+dim(L1

Error Conditions

  • ERR:DATA TYPE is thrown if you try to augment a single number to a list, a common error — use {X instead of X.
  • ERR:DIM MISMATCH is thrown if you try to augment two matrices with a different number of rows.
  • ERR:INVALID DIM is thrown if one of the arguments is a list with dimension 0, or if the result would have dimension over 999 (for lists) or 99x99 (for matrices).

Related Commands

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


The AUTO Answer Command

Command Summary

Mode command that sets Answers to AUTO.

Command Syntax

AUTO Answer

Menu Location

Press:

  1. MODE
  2. DOWN until you see Answers
  3. ENTER on AUTO

Alternatively, access the catalog.

Calculator Compatibility

TI-84 2.53MP only

Token Size

2 bytes

The AUTO Answer command is a mode command that changes the Answers mode to AUTO. The AUTO mode is in essence the same mode that lower OS models use. The calculator will evaluate a numerical expression and return a decimal or number in scientific notation, unless ►Frac is used.

In the Mathprint mode, no noticeable difference is seen unless the answer is converted to a fraction.

Related Commands

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


The AxesOff Command
AXESOFF.GIF

Command Summary

Disables the X- and Y- axes on the graph screen.

Command Syntax

AxesOff

Menu Location

Press:

  1. 2nd FORMAT to access the format menu.
  2. Use arrows and ENTER to select AxesOff.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The AxesOff command disables the X and Y axes on the graph screen, so that they aren't drawn. They can be enabled again with the AxesOn command.

(the y=x line that is drawn when both Seq and Web modes are enabled is also controlled by this command)

Generally, the AxesOff command should be used at the beginning of the program to disable the axes if the program is going to use the graph screen, since the axes get in the way. However, you should consider using StoreGDB and RecallGDB to save this setting if that's the case.

Related Commands

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


The AxesOn Command
AXESON.GIF

Command Summary

Enables the X- and Y- axes on the graph screen.

Command Syntax

AxesOn

Menu Location

Press:

  1. 2nd FORMAT to access the format menu.
  2. Use arrows and ENTER to select AxesOn.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The AxesOn command enables the X and Y axes on the graph screen, so that they are drawn. They can be disabled with the AxesOff command.

(the y=x line that is drawn when both Seq and Web modes are enabled is also controlled by this command)

Related Commands

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


The bal( Command
BAL.GIF

Command Summary

Calculates the remaining balance after n payments in an amortization schedule.

Command Syntax

bal(n,[roundvalue]

Menu Location

On the TI-83, press:

  1. 2nd FINANCE to access the finance menu.
  2. 9 to select bal(, or use arrows and ENTER.

On the TI-83+ or higher, press:

  1. APPS to access the applications menu.
  2. 1 or ENTER to select Finance…
  3. 9 to select bal(, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The bal( command calculates the remaining balance after n payments in an amortization schedule. It has only one required argument: n, the payment number. However, it also uses the values of the finance variables PV, PMT, and I% in its calculations.

The optional argument, roundvalue, is the number of digits to which the calculator will round all internal calculations. Since this rounding affects further steps, this isn't the same as using round( to round the result of bal( to the same number of digits.

Usually, you will know the values of N, PV, and I%, but not PMT. This means you'll have to use the finance solver to solve for PMT before calculating bal(); virtually always, FV will equal 0.

Sample Problem

Imagine that you have taken out a 30-year fixed-rate mortgage. The loan amount is $100000, and the annual interest rate (APR) is 8%. Payments will be made monthly. After 15 years, what amount is still left to pay?

We know the values of N, I%, and PV, though we still need to convert them to monthly values (since payments are made monthly). N is 30*12, and I% is 8/12. PV is just 100000.

Now, we use the finance solver to solve for PMT. Since you intend to pay out the entire loan, FV is 0. Using either the interactive TVM solver, or the tvm_Pmt command, we get a value of about -$733.76 for PMT.

We are ready to use bal(. We are interested in the payment made after 15 years; this is the 15*12=180th payment. bal(180) gives us the result $76781.55 — as you can see, most of the loan amount is still left to pay after 15 years.

Formulas

The calculator uses a recursive formula to calculate bal():

(1)
\begin{align} \operatorname{bal}(0)=\operatorname{PV} \end{align}
(2)
\begin{align} \operatorname{bal}(m)=\left(1-\frac{I\%}{100}\right)\operatorname{bal}(m-1)+\operatorname{PMT} \end{align}

In the case that roundvalue is given as an argument, the rounding is done at each step of the recurrence (which virtually forces us to use this formula). Otherwise, if no rounding is done (and assuming I% is not 0), we can solve the recurrence relation to get:

(3)
\begin{align} \operatorname{bal}(m)=\frac{1-\left(1-\frac{I\%}{100}\right)^m}{\frac{I\%}{100}}\operatorname{PMT}+\left(1-\frac{I\%}{100}\right)^m\operatorname{PV} \end{align}

Error Conditions

  • ERR:DOMAIN is thrown if the payment number is negative or a decimal.

Related Commands

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


The binomcdf( Command
BINOMCDF.GIF

Command Summary

Calculates the binomial cumulative probability, either at a single value or for all values

Command Syntax

for a single value:
binomcdf(trials, probability, value

for a list of all values (0 to trials)
binomcdf(trials, probability

Menu Location

Press:

  1. 2ND DISTR to access the distribution menu
  2. ALPHA A to select binomcdf(, or use arrows.

Press ALPHA B instead of ALPHA A 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 the binomial cumulative probability function. In plainer language, it solves a specific type of often-encountered probability problem, that occurs under the following conditions:

  1. A specific event has only two outcomes, which we will call "success" and "failure"
  2. This event is going to repeat a specific number of times, or "trials"
  3. Success or failure is determined randomly with the same probability of success each time the event occurs
  4. We're interested in the probability that there are at most N successes

For example, consider a couple that intends to have 4 children. What is the probability that at most 2 are girls?

  1. The event here is a child being born. It has two outcomes "boy" or "girl". In this case, since the question is about girls, it's easier to call "girl" a success.
  2. The event is going to repeat 4 times, so we have 4 trials
  3. The probability of a girl being born is 50% or 1/2 each time
  4. We're interested in the probability that there are at most 2 successes (2 girls)

The syntax here is binomcdf(trials, probability, value). In this case:

:binomcdf(4,.5,2

This will give .6875 when you run it, so there's a .6875 probability out of 4 children, at most 2 will be girls.

An alternate syntax for binomcdf( leaves off the last argument, value. This tells the calculator to compute a list of the results for all values. For example:

:binomcdf(4,.5

This will come to {.0625 .3125 .6875 .9375 1} when you run it. These are all the probabilities we get when you replace "at most 2 girls" with "at most 0", "at most 1", etc. Here, .0625 is the probability of "at most 0" girls (or just 0 girls), .3125 is the probability of at most 1 girl (1 or 0 girls), etc.

Several other probability problems actually are the same as this one. For example, "less than N" girls, just means "at most N-1" girls. "At least N" girls means "at most (total-N)" boys (here we switch our definition of what a success is). "No more than", of course, means the same as "at most".

Advanced (for programmers)

The binompdf( and binomcdf( commands are the only ones apart from seq( that can return a list of a given length, and they do it much more quickly. It therefore makes sense, in some situations, to use these commands as substitutes for seq(.

Here's how to do it:

  1. cumSum(binomcdf(N,0 gives the list {1 2 … N+1}, and cumSum(not(binompdf(N,0 gives the list {0 1 2 … N}.
  2. With seq(, you normally do math inside the list: seq(3I2,I,0,5
  3. With these commands, you do the same math outside the list: 3Ans2 where Ans is the list {0 1 … 5}.
:seq(2^I,I,1,5
can be
:cumSum(binomcdf(4,0
:2^Ans
which in turn can be
:2^cumSum(binomcdf(4,0

In general (where f() is some operation or even several operations):

:seq(f(I),I,1,N
can be
:cumSum(binomcdf(N-1,0
:f(Ans
which can sometimes be
:f(cumSum(binomcdf(N-1,0

If the lower bound on I in the seq( statement is 0 and not 1, you can use binompdf( instead:

:seq(f(I),I,0,N
can be
:cumSum(not(binompdf(N,0
:f(Ans
which can sometimes be
:f(cumSum(not(binompdf(N,0

This will not work if some command inside seq( can take only a number and not a list as an argument. For example, seq(L1(I),I,1,5 cannot be optimized this way.

Formulas

Since "at most N" is equivalent to "0 or 1 or 2 or 3 or … N", and since we can combine these probabilities by adding them, we can come up with an expression for binomcdf( by adding up values of binompdf(:

(1)
\begin{align} \operatorname{binomcdf}(n,p,k) = \sum_{i=0}^{k}\operatorname{binompdf}(n,p,i) = \sum_{i=0}^{k}\binom{n}{i}\,p^i\,(1-p)^{n-i} \end{align}

(If you're not familiar with sigma notation, $\sum_{i=0}^{k}$ just means "add the following up for each value of i 0 through k")

Error Conditions

  • ERR:DATATYPE is thrown if you try to generate a list of probabilities with p equal to 0 or 1, and at least 257 trials.
  • ERR:DOMAIN is thrown if the number of trials is at least 1 000 000, unless the other arguments make the problem trivial.

Related Commands

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


The binompdf( Command
BINOMPDF.GIF

Command Summary

Calculates the binomial probability, either at a single value or for all values

Command Syntax

for a single value:
binompdf(trials, probability, value

for a list of all values (0 to trials)
binompdf(trials, probability

Menu Location

Press:

  1. 2ND DISTR to access the distribution menu
  2. 0 to select binompdf(, or use arrows.

Press ALPHA A instead of 0 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 the binomial probability. In plainer language, it solves a specific type of often-encountered probability problem, that occurs under the following conditions:

  1. A specific event has only two outcomes, which we will call "success" and "failure"
  2. This event is going to repeat a specific number of times, or "trials"
  3. Success or failure is determined randomly with the same probability of success each time the event occurs
  4. We're interested in the probability that there are exactly N successes

For example, consider a couple that intends to have 4 children. What is the probability that 3 of them are girls?

  1. The event here is a child being born. It has two outcomes "boy" or "girl". We can call either one a success, but we'll choose to be sexist towards guys and call a girl a success in this problem
  2. The event is going to repeat 4 times, so we have 4 trials
  3. The probability of a girl being born is 50% or 1/2 each time
  4. We're interested in the probability that there are exactly 3 successes (3 girls)

The syntax here is binompdf(trials, probability, value). In this case:

:binompdf(4,.5,3

This will give .25 when you run it, so there's a .25 (1/4) probability out of 4 children, 3 will be girls.

An alternate syntax for binompdf( leaves off the last argument, value. This tells the calculator to compute a list of the results for all values. For example:

:binompdf(4,.5

This will come to {.0625 .25 .375 .25 .0625} when you run it. These are the probabilities of all 5 outcomes (0 through 4 girls) for 4 children with an equal probability of being born. There's a .0625 probability of no girls, a .25 probability of 1 girl, etc.

Advanced (for programmers)

The binompdf( and binomcdf( commands are the only ones apart from seq( that can return a list of a given length, and they do it much more quickly. It therefore makes sense, in some situations, to use these commands as substitutes for seq(.

Here's how to do it:

  1. cumSum(binomcdf(N,0 gives the list {1 2 … N+1}, and cumSum(not(binompdf(N,0 gives the list {0 1 2 … N}.
  2. With seq(, you normally do math inside the list: for example, seq(3I2,I,0,5
  3. With these commands, you do the same math outside the list: 3Ans2 where Ans is the list {0 1 … 5}.

An example:

:seq(2^I,I,1,5
can be
:cumSum(binomcdf(4,0
:2^Ans
which in turn can be
:2^cumSum(binomcdf(4,0

In general (where f() is some operation or even several operations):

:seq(f(I),I,1,N
can be
:cumSum(binomcdf(N-1,0
:f(Ans
which can sometimes be
:f(cumSum(binomcdf(N-1,0

If the lower bound on I in the seq( statement is 0 and not 1, you can use binompdf( instead:

:seq(f(I),I,0,N
can be
:cumSum(not(binompdf(N,0
:f(Ans
which can sometimes be
:f(cumSum(not(binompdf(N,0

This will not work if some command inside seq( can take only a number and not a list as an argument. For example, seq(L1(I),I,1,5 cannot be optimized this way.

Formulas

The value of binompdf( is given by the formula

(1)
\begin{align} \operatorname{binompdf}(n,p,k) = \binom{n}{k}\,p^k\,(1-p)^{n-k} = \frac{n!}{k!\,(n-k)!}\,p^k\,(1-p)^{n-k} \end{align}

This formula is fairly intuitive. We want to know the probability that out of n trials, exactly k will be successes, so we take the probability of k successes - $p^k$ - multiplied by the probability of (n-k) failures - $(1-p)^{n-k}$ - multiplied by the number of ways to choose which k trials will be successes - $\binom{n}{k}$.

Error Conditions

  • ERR:DOMAIN is thrown if the number of trials is at least 1 000 000 (unless the other arguments make the problem trivial)

Related Commands

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


The ceiling() Command

ceiling.png

Command Summary

Returns the ceiling of a number.

Command Syntax

ceiling(value)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press 1 to enter the Number submenu.
  • Press 7 to select ceiling(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The ceiling() command rounds a number up to the nearest integer at least as large as the number. For instance, ceiling(π) returns 4, while ceiling(-π) returns -3.

There are several commands available to round a number to an integer in slightly different ways:

  • int() and floor() — like ceiling(), but round down instead.
  • iPart() — truncates a number to just its integer part (or, if you prefer, rounds a number toward 0).
  • round() — rounds to a specific place value, not just to an integer, but round(x,0) will round x to the nearest integer, up or down.

ceiling() can also be applied to complex numbers, lists, and matrices, rounding everything that there is to round in each of them.

:ceiling(3)
           3
:ceiling({-π,π})
           {-3  4}

Related Commands

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


The char() Command

char.png

Command Summary

Returns a character given its ASCII code.

Command Syntax

char(code)

Menu Location

  • Press 2nd MATH to enter the MATH popup menu.
  • Press D to enter the String submenu.
  • Press A to paste char(.

Calculator Compatibility

This command works on all calculators.

Token Size

2 bytes

The char() command converts an integer between 0 and 255 to the corresponding character in the calculator's internal code (which is a modification of ASCII). It can also operate on a list or matrix by converting each of their elements to a character.

This command, and its inverse ord(), can be useful for programs that deal with arbitrary strings (which could, potentially, contain any character), but they can come up in other cases as well. For example, since the letters A..Z are consecutive characters in the calculator's internal code, with A being char(65), you can calculate the nth letter in the alphabet with the expression char(n+64).

There are two special values of char() to be aware of. The character given by char(0) is actually the empty string, which you usually want to avoid using; the character given by char(13) is a newline "enter" character, which is replaced by ":" when you type it somewhere. If you actually want to store char(13) to a string, you have to use the char() command.

Advanced Uses

TI-Basic does not allow lists to contain picture variables, and in many cases (such as tilemaps) you want to get around this limitation. One way to do so is to name the variables "tile1", "tile2", "tile3", and so on, with only the number changing — then #("tile"&string(n)) gives the nth picture variable.

A more efficient way is to assign the pictures numbers in a different range, such as 65-90, and name the variables "tilea", "tileb", "tilec", etc. Then, #("tile"&char(n)), which is faster, converts a number to the corresponding picture variable. This allows for a maximum of 146 different tiles, if you use all the characters that could conceivably be part of a variable name.

Error Conditions

260 - Domain error happens when the character code isn't in the range 0..255.

Related Commands

See Also

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


The checkTmr( Command
CHECKTMR.GIF

Command Summary

Returns the number of seconds since the timer was started.

Command Syntax

checkTmr(Variable)

Menu Location

This command can only be found in the catalog. Press:

  1. 2nd CATALOG to enter the command catalog
  2. C to skip to command starting with C
  3. Scroll down to checkTmr( and select it

Calculator Compatibility

TI-84+/SE/CSE

Token Size

2 bytes

The checkTmr( command is used together with the startTmr command to determine how much time has elapsed since the timer was started on the TI-84+/SE calculators. In particular, it returns the number of seconds since the built-in timer was started. An application of these commands is timing different commands or pieces of code, as well as countdowns in games, or a time-based score (such as in Minesweeper).

To use the timer, you first store startTmr to a variable (usually, a real variable) whenever you want the count to start. Now, whenever you want to check the elapsed time, you can use checkTmr( with the variable from above, giving you the number of seconds that have passed. Using checkTmr( doesn't stop the timer, you can do it as many times as you want to.

In the case of Minesweeper, for example, you would store startTmr to, for example, T, after setting up and displaying the board, display the result of checkTmr(T) in the game's key-reading loop, and store checkTmr(T) to the player's score if he wins.

Advanced Uses

To time a command or routine using startTmr and checkTmr(, use the following template:

:ClockOn
:startTmr→T
:Repeat checkTmr(Ans
:End
:For(n,1,(number)                    //sequence variable n
   (command(s) to be tested)
:End
:checkTmr(T+1)/(number)

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

While this method eliminates human error from counting, it's prone to its own faults. For example, startTmr and checkTmr( always return the time rounded down to a whole second. To take this into account, replace the last line:

:(checkTmr(T+{1,0})/(number)

When testing code, be aware that many different things affect the time: the strength of the batteries, the amount of free RAM, and including the closing parenthesis on the For( loop. The last one, in particular, has an impact when using a single-line If statement or one of the IS>( and DS<( commands on the first line inside a For( loop.

Related Commands

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


The checkTmr() Command

checktmr.png

Command Summary

Checks the value of the system clock.

Command Syntax

checkTmr(time)

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

2 bytes

The checkTmr() command, together with startTmr() uses the built-in system clock to measure the time (in seconds) that passed between two points of the program. Make sure that the clock is on (with ClockOn before using these).

The name of the commands reflects their use: you can think of a startTmr() call as creating and starting a timer:

:startTmr()→timer

The checkTmr() command will then return the number of seconds that have elapsed on the timer (without stopping it):

:Disp "Seconds elapsed:",checkTmr(timer)

This is a good abstraction and you don't need to know the details of how startTmr() and checkTmr() work to use them. In reality, what startTmr() actually returns is the current value of a system timer (which increases by 1 every second). The checkTmr() command does the same thing, but subtracts its parameter: so checkTmr(x) is equivalent to startTmr()-x.

Because both startTmr() and checkTmr() deal with whole numbers of seconds, the resulting difference in time could be off by up to a second in either direction. That is, if checkTmr() gives 15 seconds as the time, you know the time that actually passed is between 14 and 16 seconds.

Advanced Uses

The startTmr() and checkTmr() commands can be used to figure out how much time a command or routine takes with much greater precisions by running it multiple times. For example:

:startTmr()→t
:For i,1,1000
: somecmd()
:Disp checkTmr(t)

Suppose that the result displayed was 100 seconds. This is accurate to 1 second, so the actual time was between 99 and 101 seconds. However, this actual time is for 1000 repetitions of somecmd() (we assume that the time the code takes to increment i is negligible, although that may also be taken into account). So somecmd() repeated only once takes between 99/1000 and 101/1000 seconds, so the actual time is 100 ms, measured to within 1 millisecond error.

See Code Timings for more information on this, as well as the results of some common comparisons.

Related Commands

See Also

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


The Circle( Command
CIRCLE.GIF

Command Summary

Draws a circle.

Command Syntax

Circle(X,Y,r)

(83+ and higher only)
Circle(X,Y,r,{i})

(84+ CSE only)
Circle(X,Y,r

Menu Location

Press:

  1. Press [2ND] [PRGM] to enter the DRAW menu
  2. Press [9] to insert Circle(

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

Circle(X,Y,r) will draw a circle at (X,Y) with radius r. X and Y will be affected by the window settings. The radius will also be affected by the window settings.

:Circle(5,5,5)

Advanced Uses

The radius of a circle is affected by the window settings. This means that if the x- and y-increment is two, the radius will be two pixels. However, there is another way to take advantage of this to draw ellipses. If the x- and y-increment are different, then the shape will not be a circle. For instance, with Xmin=0, Xmax=20, Ymin=0, and Ymax=31, Circle(10,10,2) will draw an ellipse, where the width is greater than the height.

Optimization

If a complex list such as {i} is passed to Circle( as the fourth argument, the "fast circle" routine is used instead, which uses the symmetries of the circle to only do 1/8 of the trig calculations. For example:

:Circle(0,0,5
can be
:Circle(0,0,5,{i

Any list of complex numbers will work as the fourth argument in the same way, but there's no benefit to using any other list.

Note: The "fast circle" routine is not available on the TI-84+CSE or TI-84+CE calculators.

Command Timings

The ordinary Circle( is extremely slow. The fast circle trick discussed above cuts the time down to only about 30% of the "slow Circle(" time! While still not instant, this is faster than any replacement routine that can be written in TI-Basic.

For small radii, replace Circle( with Pt-On( instead.

Related Commands

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


The CLASSIC Command

Command Summary

Mode command that puts the calculator into Classic mode.

Command Syntax

CLASSIC

Menu Location

Press:

  1. MODE
  2. DOWN until you reach MathPrint or Classic
  3. ENTER on Classic

Alternatively, use the catalog.

Calculator Compatibility

TI-84 2.53MP only

Token Size

2 bytes

CLASSIC will put the calculator into Classic mode as opposed to MathPrint mode. The Classic mode will make the calculator display everything as pre-MathPrint 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

Advanced Uses

When in Classic mode, text and numbers are displayed much faster on the home screen and the function menus load faster. This can be useful in games that use the home screen, or just with calculations in general.

Related Commands

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


The Clear Entries Command
CLEARENTRIES.GIF

Command Summary

Clears the history of commands previously entered on the homescreen.

Command Syntax

Clear Entries

Menu Location

Press:

  1. 2nd MEM to access the memory menu.
  2. 3 to select Clear Entries, or use arrows and ENTER.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

Normally, by pressing 2nd ENTER repeatedly, you can cycle through some of the recent entries on the home screen. With the Clear Entries command, this history is cleared (only Clear Entries remains in the history).

This can be used to free some memory, although it's recommended not to do this in a program (because clearing things without asking first isn't nice). Aside from that, maybe the only reason to use Clear Entries is to protect your privacy — although someone looking at your entries will know you cleared something, so it's not that effective.

Related Commands

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


The ClockOff Command
CLOCKOFF.GIF

Command Summary

Turns off the clock display in the mode screen.

Command Syntax

ClockOff

Menu Location

This command can only be found in the catalog. Press:

  1. 2nd CATALOG to enter the command catalog
  2. C to skip to command starting with C
  3. Scroll down to ClockOff and select it

Calculator Compatibility

TI-84+/SE

Token Size

2 bytes

The ClockOff command turns off the clock display at the bottom of the mode screen on the TI-84+/SE calculators. You can turn the clock back on by using the ClockOn command, or by selecting 'TURN CLOCK ON' ,displayed in place of the clock on the mode screen.

The ClockOff command does not actually turn the clock off. The time can still be accessed through use of the getTime and getDate commands, and all their cousins.

Related Commands

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


The ClockOff Command

clockoff.png

Command Summary

Turns off the hardware clock.

Command Syntax

ClockOff

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

2 bytes

The ClockOff Command turns off the calculator's clock as far as the time and date commands are concerned: that is, the timer used by startTmr(), getTime(), and other commands will not keep updating every second, but will stay the same until the clock is turned on again.

It's not usually a good idea to use this in a program: there's no real benefit to doing so (it doesn't make the calculator run faster or anything like that) but there's the real drawback that it throws off the calculator's time. However, the mere existence of this command means that you should probably use ClockOn anytime you need to use the time and date commands.

Since it modifies the global status of the calculator, ClockOff can't be used in a function.

Error Conditions

450 - Invalid in a function or current expression happens when ClockOff is used inside a function.

Related Commands

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


The ClockOn Command
CLOCKON.GIF

Command Summary

Turns on the clock display in the mode screen.

Command Syntax

ClockOn

Menu Location

This command can only be found in the catalog. Press:

  1. 2nd CATALOG to enter the command catalog
  2. C to skip to command starting with C
  3. Scroll down to ClockOn and select it

Calculator Compatibility

TI-84+/SE

Token Size

2 bytes

The ClockOn command turns on the clock display at the bottom of the mode screen on the TI-84+/SE calculators. Alternatively, you can scroll down to the 'TURN CLOCK ON' message that is displayed in place of the clock on the mode screen and press ENTER twice. You can turn the clock off by using the ClockOff command.

Related Commands

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


The ClockOn Command

clockon.png

Command Summary

Turns on the hardware clock.

Command Syntax

ClockOn

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

2 bytes

The ClockOn command turns on the calculator's clock, used by most time and date commands. Only when the clock is on, will the value returned by startTmr(), getTime(), and other commands actually change with the passage of time. If you write a program that uses any of these commands, be sure to include this command at the beginning of the program.

Since it modifies the global status of the calculator, ClockOn can't be used inside a function. If you're writing a function that depends on measuring time (so you need the clock to be on), the best thing you can do is use the isClkOn() command to check if the clock is on or off, and return an error message if it's off.

Error Conditions

450 - Invalid in a function or current expression happens when ClockOn is used in a function.

Related Commands

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


The ClrAllLists Command
CLRALLLISTS.GIF

Command Summary

Sets the size of all defined lists to 0 (equivalent to applying the ClrList command to all defined lists).

Command Syntax

ClrAllLists

Menu Location

Press:

  1. 2nd MEM to access the Memory menu
  2. 4 to select ClrAllLists, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

The ClrAllLists command sets the dimension (length) of all lists to zero. This is virtually equivalent to deleting the lists, except for two differences:

  • The lists still exist and will show up in the list menu and the memory management menu.
  • The dim( command will return 0 for a cleared list, rather than an error.

However, accessing a cleared list in any other way will return an error, just as for a deleted list.

The ClrAllLists command should never be used in a program you give to someone else or upload - unless the user is aware of this effect, they might lose important data stored in one of their lists. There is no way to limit the effect of ClrAllLists, so a program should use ClrList instead to avoid affecting unrelated lists (this is assuming you already want to use this questionably-useful effect).

Outside a program (or in a program for personal use), you might use this command to clear the contents of your lists to free up memory, while still not deleting the lists. This might possibly be convenient. Maybe.

Related Commands

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


The ClrDraw Command
CLRDRAW.GIF

Command Summary

Clears the graph screen, redrawing functions, plots, and axes/grid/labels, if applicable.

Command Syntax

ClrDraw

Menu Location

Press:

  1. 2nd PRGM to enter the DRAW menu
  2. 1 or ENTER to select ClrDraw

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ClrDraw command is useful clearing away something drawn on the graph screen; in particular, you want to do this at the beginning of a program that uses the graph screen, to get rid of anything that might be on it initially. If there are functions, plots, axes, labels, or grid enabled, these will be redrawn even after you ClrDraw. If you don't want these, you should turn them off before the ClrDraw command.

Like many other drawing commands, if you're outside a program and on the graph screen, you can use this command directly, without going to the home screen. Just select ClrDraw from the menu, and the screen will be cleared immediately.

Advanced Uses

Unless the final state of the graph screen is the intended effect of the program, you want to use ClrDraw at the end of the program so that the user doesn't have to deal with it.

Caution: if the graph screen is displayed even before you execute ClrDraw, the user variable Y will be reset to 0. This might be useful as a side effect, but it's more likely to turn out to be a nuisance if you were relying on Y to store something useful. Also, such a wacky effect might get removed in later OS versions1, so it's a gamble relying on it to work for all users.

The RecallPic command does not erase what is previously on the graph screen when recalling a picture. Unless this is what you intend, use ClrDraw to erase the graph screen's old contents before recalling a picture.

Optimization

The ClrDraw command is not the only way to clear the screen. If something changes about the state of the functions or plots plotted on the graph, about the window dimensions, or the axes, grid, and labels, the graph screen will be marked as 'dirty' by the calculator, and will be cleared the next time you display it.

Don't be too confident about relying on this however. For example, if you cleared Y1 before displaying the graph, and Y1 previously contained something, the graph will be redrawn. However, if Y1 never existed, then you haven't changed anything, and the graph will remain.

A lot of people choose their preferred window settings using the following two commands, which sets the window to X= -47..47, Y= -31..31:

ZStandard:ZInteger

Since this actually switches two window settings, at least one will be different from the previous settings, so the next time the graph screen is shown, it will be cleared without a ClrDraw command. There are other friendly window settings that you can use as well.

Related Commands

See Also

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


The ClrDraw Command

clrdraw.png

Command Summary

Clears the graph screen, redrawing any functions, plots, or axes/grid/labels.

Command Syntax

ClrDraw

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 ClrDraw command clears away anything drawn on the graph screen — that is, the result of any of the graphics commands, except for Graph (which you can only clear with ClrGraph). It also leaves alone any functions or plots (which are disabled by FnOff and PlotsOff, respectively), as well as axes, labels, a grid, etc. (which can be disabled by the setGraph() command).

Be warned that it doesn't update the screen. For example, if you run the following program:

:circ()
:Prgm
:Circle 0,0,5
:ClrDraw
:EndPrgm

it will draw a circle and then end on the graph screen with the circle still drawn. The screen will actually update the next time you change something on the graph screen; you can also use DispG to update it (although in the program above, DispHome might be more appropriate).

Related Commands

See Also

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


The ClrHome Command
CLRHOME_ANIMATED.GIF

Command Summary

Clears the home screen of any text or numbers.

Command Syntax

ClrHome

Menu Location

While editing a program, press:

  1. PRGM to enter the PRGM menu
  2. RIGHT to enter the I/O menu
  3. 8 to choose ClrHome, or use arrows

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

There are numerous times in a program that you need a clear screen, so that you can display whatever text you want without it being interrupted. One place, in particular, is at the beginning of a program, since the previous program call(s) and any other text is typically still displayed on the screen. The simple ClrHome command is the command you use to clear the home screen.

When you use the ClrHome, it resets the cursor position to the top left corner of the home screen. This is what the Disp and Pause commands use as the reference for what line to display their text on, but it does not have any effect on Output(.

Advanced Uses

You want to make sure to clear the home screen when exiting programs (at the end of a program). This ensures that the next program that the user runs will not have to deal with whatever text your 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.

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/clrhome


The ClrHome Command

clrhome.png

Command Summary

Clears the home screen.

Command Syntax

ClrHome

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 ClrHome command clears the home screen — not the I/O screen where the result of commands like Disp or Output is displayed (you'd need ClrIO for that), but the screen where you run programs and evaluate expressions. This isn't usually something you want a program to clear, so this isn't a very exciting command.

It also has the drawback that the ClrHome command itself (or the program it's used in) is displayed on the home screen after it is cleared, so the end result is not a blank screen but something like what you see in the screenshot to the right.

Finally, ClrHome cannot be used inside a function, because functions aren't allowed to modify the state of the calculator.

Error Conditions

450 - Invalid in a function or current expression happens when ClrHome is used inside a function.

Related Commands

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


The ClrList Command
CLRLIST.GIF

Command Summary

Sets the dimension of a list or lists to 0.

Command Syntax

ClrList list1, [list2, list3, …]

Menu Location

Press:

  1. STAT to access the statistics menu
  2. 4 to select ClrList, or use arrows.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

ClrList sets the length of a list (or several lists) to 0. This is virtually equivalent to deleting the list, except for several differences:

  • The list still exists — it will be shown in the memory management menu and the list menu
  • Calling the dim( command on it will return 0, rather than an error.
  • ClrList can clear multiple lists at the same time

Advanced Uses

You might use ClrList when building up a list element by element and using dim( in the process:

:ClrList L1
:While 10>dim(L1
:Input X
:X→L1(1+dim(L1
:End

Optimization

Using DelVar instead of ClrList allows you to save a tiny bit of memory (between 12 and 16 bytes) that ClrList doesn't delete, while keeping almost every aspect of the list clearing the same. If you are clearing several lists, you can separate them with commas as the arguments to ClrList, which can save space. Using ClrList is also substantially faster than DelVar if the list is going to be cleared many times.

Error Conditions

  • ERR:SYNTAX is thrown if you leave off the symbol when referring to a custom list (i.e., ClrList B will not work; you have to use ClrList ∟B).

Related Commands

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


The ClrTable Command
CLRTABLE.GIF

Command Summary

Clears saved calculations for the table screen.

Command Syntax

ClrTable

Menu Location

While editing a program, press:

  1. PRGM to access the program menu.
  2. RIGHT to access the I/O submenu.
  3. 9 to select ClrTable.

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

The ClrTable command clears all calculations for the table screen shown if you press 2nd TABLE. That is, all already-calculated values in the table are cleared, and TblInput is deleted. In IndpntAuto and DependAuto mode, this usually isn't noticeable because the table will be recalculated almost immediately when you next look at it (unless one of the entered functions is so complicated it takes a while to calculate). This mainly has an effect in IndpntAsk or DependAsk mode, where the corresponding parts of the table will be cleared entirely.

Advanced Uses

As a side effect, ClrTable seems to have all the effects of ClrDraw — it clears the graph screen, and any equations or plots will be regraphed the next time the graph screen is displayed.

Command Timings

ClrTable and ClrDraw take the same amount of time to clear the screen.

Related Commands

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


The conj( Command
CONJ.GIF

Command Summary

Calculates the complex conjugate of a complex number.

Command Syntax

conj(value)

Menu Location

Press:

  1. MATH to access the math menu.
  2. RIGHT, RIGHT to access the CPX (complex) submenu
  3. ENTER to select conj(.

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

conj(z) returns the complex conjugate of the complex number z. If z is represented as x+iy where x and y are both real, conj(z) returns x-iy. Also works on a list of complex numbers.

conj(3+4i)
     3-4i

The conjugate of a number $z$ is often written $\overline{z}$, and is useful because it has the property that $z\overline{z}$ and $z+\overline{z}$ are real numbers.

Related Commands

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


The Connected Command
CONNECTED.GIF

Command Summary

Sets all equations to use the connected graphing style, and makes it the default setting.

Command Syntax

Connected

Menu Location

Press:

  1. MODE to access the mode menu.
  2. Use arrows to select Connected.

Calculator Compatibility

TI-83/84/+/SE (Not available on TI-84+CE calculators)

Token Size

2 bytes

The Connected command sets all equations to use the usual graph style - a connected line. In addition, this graph style is made the default, so that when a variable is deleted it will revert to this graph style. The other possible setting for this option is Dot.

Compare this to the GraphStyle( command, which puts a single equation into a specified graph style.

The Connected and Dot commands don't depend on graphing mode, and will always affect all functions, even in other graphing modes. The exception to this is that sequence mode's default is always the dotted-line style, even when Connected mode is set. The Connected command will still change their graphing style, it just won't change the default they revert to.

In addition to graphing equations, this setting also affects the output of DrawF, DrawInv, and Tangent(.

Related Commands

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


The CoordOff Command
COORDOFF.GIF

Command Summary

Turns off the cursor coordinate display on the graph screen.

Command Syntax

CoordOff

Menu Location

Press:

  1. 2nd FORMAT to access the graph format menu
  2. Use arrows and ENTER to select CoordOff

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

When moving a cursor on a screen, it's possible for the calculator to display the coordinates of the current point (either polar or rectangular coordinates, depending on which of RectGC or PolarGC is set). The CoordOff command turns off this option.

To turn it on, use the CoordOn command.

Related Commands

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


The CoordOn Command
COORDON.GIF

Command Summary

Turns on the cursor coordinate display on the graph screen.

Command Syntax

CoordOn

Menu Location

Press:

  1. 2nd FORMAT to access the graph format menu
  2. Use arrows and ENTER to select CoordOn

Calculator Compatibility

TI-83/84/+/SE

Token Size

2 bytes

When moving a cursor on a screen, it's possible for the calculator to display the coordinates of the current point (either polar or rectangular coordinates, depending on which of RectGC or PolarGC is set). The CoordOn command turns on this option (to disable it, use the CoordOff command).

The coordinates are displayed in practically every situation when you're moving a cursor on the graph screen, even including the Trace, Input or Select( commands in a program. The interactive mode of Text( and the Pen tool are the exceptions — this is because these two situations involve a pixel coordinate, and not a point.

Related Commands

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


The cos( Command
COS.GIF

Command Summary

Returns the cosine of a real number.

Command Syntax

cos(angle)

Menu Location

Press [COS]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

cos(θ) returns the cosine of θ, which is defined as the x-value of the point of intersection of the unit circle and a line containing the origin that makes an angle θ with the positive x-axis

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 cos( command also works on a list of real numbers.

In radians:

cos(π/3)
    .5

In degrees:

cos(60)
    .5

Advanced Uses

You can bypass the mode setting by using the ° (degree) and r (radian) symbols. These next two commands will return the same values no matter if your calculator is in degrees or radians:

cos(60°)
    .5
cos(π/3^r)
    .5

Error Conditions

  • ERR:DATA TYPE is thrown if you supply a matrix or a complex argument.
  • ERR:ARGUMENT is thrown if you use more than one number.

Related Commands

See Also

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


The cos() Command

cos.png

Command Summary

Takes the cosine of a number (usually, an angle).

Command Syntax

cos(angle)

Menu Location

Press the COS button to enter cos(.

Calculator Compatibility

This command works on all calculators.

Token Size

1 byte

The cos() command returns 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.

For many common angles, cos() 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, cos() can be used with complex numbers as well.

:cos(60°)
           1/2
:cos(x+2π)
          cos(x)
:cos(πi/2)
          cosh(π/2)

If cos() is applied to a list, it will take the cosine of every element in the list.

Advanced Uses

The cos() of a matrix is not (in general) the same as taking the cosine of every element of the matrix. A different definition is used to compute the result; see Matrices and Their Commands. It requires the matrix to be square and diagonalizable in order to apply.

Error Conditions

230 - Dimension happens when taking cos() of a matrix that isn't square.

260 - Domain error happens when taking cos() of a complex number in degree or gradian mode.

665 - Matrix not diagonalizable happens when taking cos() of a matrix that isn't diagonalizable.

Related Commands

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


The cosֿ¹( Command
COSINVERSE.GIF

Command Summary

Returns the inverse cosine (also called arccosine)

Command Syntax

cosֿ¹(number)

Menu Location

Press:

  1. [2nd]
  2. [cosֿ¹]

Calculator Compatibility

TI-83/84/+/SE

Token Size

1 byte

cosֿ¹( returns the arccosine of its argument. It is the inverse of cos(, which means that cosֿ¹(n) produces an angle θ such that cos(θ)=n.

Like cos(, the result of cosֿ¹( depends on whether the calculator is in Radian or Degree mode. However, unlike cosine, the result is in degrees or radians, not the argument. A full rotation around a circle is 2π radians, which is equal to 360°. The conversion of θ=cosֿ¹(n) from radians to degrees is θ*180/π and from degrees to radians is θ*π/180. The cosֿ¹( command also works on a list.

The cosֿ¹( function can be defined for all real and complex numbers, but assumes real values only in the closed interval [-1,1]. Because Z80 calculators have their trigonometric functions and inverses restricted only to real values, the calculator will throw ERR:DOMAIN if the argument is outsi