### [LET] result = b*(c+d)/e^f*sin(g+h)+max(i)+j%k

LET uses mathematical formula notation to compute a value and assign it to a variable. The vector on the left side of the equal sign is given the result of the formula on the right side of the equal sign. The formula may be a mathematical expression or a logical expression (see below). The formula may contain variable names (vectors), named variables (enums and named constants), numerical constants, and literal vectors. It may also invoke any of a number of Statistics101 math command names as unary functions, such as LOG, SIN, and STDEV (see table below), as well as subroutines that you write yourself using NEWCMD that have one input vector and one output vector.

You may omit the LET command name. The equal sign is sufficient. For example,

`LET a = sin(3.14159/180*30)`

can also be written as:

`a = sin(3.14159/180*30)`

If you omit the LET command name and happen to choose a result variable name that is also a command name, you will get an error. For example,

`data = SQRT(1 2 3 4 5)`

produces the error message "ERROR: Invalid variable format "=" (Number, variable, sequence, or list expected) in command DATA,...". That is because "data" is also a command name and is interpreted as such because it is the first word on the line. It is best to change the result variable name, but if you insist on using it, you can put the LET command word at the beginning of the line like this:

`LET data = SQRT(1 2 3 4 5)`

and that will be accepted.

The valid operators are shown in the following table. Use these operators exactly as you would in a formula. Their precedence is defined so that, in the absence of parentheses, the mathematical operations are executed in the customary order. The concatenation operator (&) appends the vector on its right to the vector on its left. It is of the same precedence as addition and subtraction.

Operation

Operator

Precedence

Addition

+

low

Subtraction

-

low

Concatenation

&

low

Multiplication

*

medium

Division

/

medium

Remainder

%

medium

Power

^

high

The minus sign "-" in its common usage has four different meanings: as a subtraction operator (a - b), as a "change sign" operator (-a), as an indicator that a literal number is less than zero (-4.5E-3), and as a hyphen in a variable name ("class-grades") . When used following a variable name, you should put a space before the minus sign so it isn't interpreted as a hyphen. Otherwise, you will get a syntax error message. If Statistics101 is unhappy with your use of minus signs, it will prompt you to correct it.

As always, a decimal number must have at least one place before the decimal point, e.g., "0.5" instead of ".5".

The following table lists the mathematical functions that are valid in the formulas of the LET command. These functions have the highest precedence and are executed prior to any of the above mathematical operators. The functions behave exactly as do the commands having the same name. The mathematical functions, when used with LET, can take only one argument. This means they cannot accept keywords as they can when used as commands. Therefore a function like STDEV that allows a keyword when used as a command will perform only its default behavior when it is used in the LET command. To make those computations that are subject to keywords available, new names are defined with the keyword added as part of the name, separated by an underscore. For example a standalone "STDEV POP" command would become "STDEV_POP" when used in the LET command and "SORT DESCENDING" becomes "SORT_DESCENDING" in the LET command. Similarly, the INTEGER command has been broken into four separate function names based on its keywords: INTEGER_CEILING, INTEGER_FLOOR, INTEGER_ROUND, and INTEGER_TRUNCATE. The table also lists these variations.

Within the LET command all these function names are "reserved". That means that you cannot use any variable name in a LET command that is the same as a function name because the variable name will be interpreted as a function name.

Function

Comment

ABS

Returns the absolute value of its argument.

ACOS

Returns radians.

ASIN

Returns radians.

ATAN

Returns radians.

COS

Argument must be in radians.

DEDUP

Returns a vector that is its input vector with all duplicates removed.

EXP

Computes e to a power for each element of its argument.

FRACTION

Returns the fractional part of each element of its argument.

Truncates each element of its argument to integer. Does not round. These are two different names for the identical function. The default behavior of the INTEGER command is to truncate, so the added keyword is optional.

INTEGER_CEILING

Chooses the smallest (closest to negative infinity) integer that is not smaller than the original number. The ceiling of 1.65 is 2.0; the ceiling of -1.65 is -1.0.

INTEGER_FLOOR

Chooses the largest (closest to positive infinity) integer that is not greater than the original number. The floor of 1.65 is 1.0; the floor of -1.65 is -2.0

Chooses the integer closest to the original number. If two possible integers are equally close, the one that is even is chosen. This has the effect of a 50 percent chance of rounding down and a 50 percent chance of rounding up.

LOG

Computes log base e of each element of its argument.

LOG10

Computes log base 10 of each element of its argument.

MAX

Returns the most positive element of its argument.

MEAN

Computes the mean of its argument.

MEDIAN

Computes the median of its argument.

MIN

Returns the most negative element of its argument.

MODE

Computes the mode of its argument.

NORMAL

Generates random numbers from a standardized normal distribution (mean = 0, standard deviation = 1). Its argument specifies how many random numbers to generate.

NORMALPROB

Computes the normal cumulative probability (area under the normal curve) from negative infinity to z for each element, z, of its argument.

NORMALPROBINV

Computes the one-tailed z values for each element, p, of its argument vector, where p is a probability.

PRODUCT

Computes the product of all elements of its argument.

RANKS

Returns the ranks of the elements of its vector argument. The lowest valued element has rank 1.

RANKS_DESCENDING

Returns the ranks of the elements of its vector argument in descending order. The highest valued element has rank 1.

ROUND

Rounds to closest integer. Rounds up if two integers are equidistant.

SHUFFLE

Returns the contents of its argument rearranged randomly.

SIGN

Returns a "1" or "-1" for each element in its argument depending on whether the element is positive or negative. Zero is considered positive and returns a 1.

SIGN_SIGNUM

Returns a "1" or "-1" for each element in its argument depending on whether the element is positive or negative. Zero returns a zero.

SIN

Argument must be in radians.

SIZE

Returns the size of its vector argument.

SORT

Returns vector sorted in ascending order.

SORT_DESCENDING

Returns vector sorted in descending order.

SQRT

Computes the square root of its argument.

SQUARE

Computes the square of its argument.

STDEV

Computes the sample standard deviation only, not the population standard deviation.

STDEV_POP

Computes the population standard deviation.

SUM

Computes the sum of all elements of its argument.

TAGSORT

Returns tags for vector elements sorted in ascending order.

TAGSORT_DESCENDING

Returns tags for vector elements sorted in descending order.

TAN

Argument must be in radians.

TIME

Returns current time in milliseconds.

UNIFORM

Generates random numbers from a standardized uniform distribution (lower limit = 0, upper limit = 1). Its argument specifies how many random numbers to generate.

VARIANCE

Computes the sample variance only, not the population variance.

VARIANCE_POP

Computes the population variance.

The mathematical functions can be invoked with or without parentheses as follows.

`LET vec1 = LOG vec2`

or

`LET vec1 = LOG(vec2)`

The parentheses are required if the argument is an expression:

`LET vec1 = LOG(vec2 + vec3)`

Although parentheses are used for determining execution order, they can also be used to enter a literal vector into the equation. For example, this is legal:

`LET vec1 = LOG(1 2 3 4 5)`

You can also use multiple and sequence format (m#n and m,n respectively) to express literal (unnamed) vectors. For example, the above line could also be written like this using the sequence format:

`LET vec1 = LOG(1,5)`

Logical expressions

The LET command can also be used to assign the result of logical expressions to variables. The result of a logical expression is always either true or false. The constants true and false are predefined, so the following assigns true to vec1:

LET vec1 = true

The following also assigns true to vec1, since that is the result of the logical expression on the right hand side of the equal sign (the LET may be omitted as shown here):

vec2 = sin(0.1) < 0.5

The logical expressions may be more complex, as in this arbitrary example (assumes a, b, and c are defined earlier in the program):

vec3 = a < b + 4 and c > 0 and sin(0.1) < 0.5

Remember that all the tests, such as <, =, and between only compare the first element of the vectors involved in the test.

You can use variables containing logical values anyplace that logical expressions are allowed:

IF vec1 and vec2

...

END

or even in another LET command:

vec4 = vec1 or vec3 and sqrt(x) > 3

User-defined functions

If you define a subroutine that has only one input variable and one output variable, you can invoke that subroutine within a LET command. For example, if you define a subroutine of the form

`NEWCMD MYSUB inVec outVec   . . .END`

where you can use any name you like instead of "mysub", you can invoke it in a LET command as you would any mathematical function:

```. . .LET resultVec = 3 * MYSUB(vecA) + COS(vecB). . .
```

You can see an example of such a usage in the example column to the right.

Debugging

Statistics101 Version 3.0 and above: Each LET command is treated as a single step by the debugger.

Statistics101 Versions prior to 3.0: If you are using the debugger to find an error in your program, be aware that each operator and each function in a LET command takes one program "step". Therefore, if your program is stopped on a line containing the LET command, it may take several steps (Run>Step or Ctrl-T or the "Step" button) to complete the entire LET command before moving to the next program line. You can see the intermediate results if you select the "Show Internal Variables" button on the Debug window.

The operators that you use in the LET command, such as "+", "-", "^", etc. are actually converted into invocations of the ADD, SUBTRACT, POWER, etc. commands to be executed. The "&" operator is converted to a COPY command. The function names you use, such as ABS, SIN, etc. get converted into the commands of the same name. The "=" sign is converted to a COPY command.

For example, the command:

`LET A = B + C`

will be converted internally (not visible to you) into:

`ADD B C internal#001COPY internal#001 A`

where internal#001 is an internal temporary variable assigned to hold the intermediate result. Therefore, it will take two debugging steps, one for the plus operator (ADD) and one for the equals (COPY) operator, to step through that command line. But, if you call for the same computation using the ADD command:

`ADD B C A`

it will be completed in one debugging step.

This example graphs a circle:

```NAME 0.017453292519943295 degToRad 'Multiply degrees by this to get radiansCOPY 0,360 angles  'in degrees
COPY 10 radius
LET xValues = radius * cos(angles*degToRad)
LET yValues = radius * sin(angles*degToRad)
PRINT xValues yValues
XYGRAPH xValues yValues```

This example prints out some powers of two:

```'Program to print out the first 11 'powers of two.
COPY 0,10 exponents
LET powersOfTwo = 2^exponents
PRINT powersOfTwo
```

The output of this program is:

`powersOfTwo: (1.0 2.0 4.0 8.0 16.0 32.0 64.0 128.0 256.0 512.0 1024.0)`

This example computes the sum of a power series:

```'To cover a distance, first you must'cover half the distance, then half
'the remaining distance, and so on.
'How far will you have gone after 20
'such moves?
'Assume the distance is 10 miles.
COPY 10 distance
COPY 1,20 powers
LET seriesSum = distance*sum(0.5^powers)
PRINT seriesSum```

The next example compares a program that uses the LET command with a similar program that does not use the LET command.

```INCLUDE "lib\mathConstants.txt"'
'Program to plot a damped sine wave
COPY 100 frequency
COPY 1,1000 t
'
'The LET command computes a damped sine
'wave in one line:
LET amplitude = e^(-t/(2*frequency)) * sin(2*pi*t/frequency)
XYGRAPH t amplitude
'
'To do the same thing without the LET
'command takes 7 lines and is harder
'to understand:
MULTIPLY  2 pi t twoPiT
DIVIDE twoPiT frequency sinArg
SIN sinArg factor1
MULTIPLY 2 frequency twoFreq
DIVIDE t twoFreq -1 exponent
POWER e exponent factor2
MULTIPLY factor1 factor2 amplitude2
XYGRAPH t amplitude2```

Both versions produce the same graph: This next example shows the use of a literal vector "0,720" in the LET command instead of a variable name. The first line computes the sin of the angles from 0 to 720 degrees in steps of one degree. The second line graphs the result:

```LET vec1 = sin(3.14159/180 * 0,720)XYGRAPH "" "Degrees" 0,720 vec1
```

The concatenation operator (&) appends the vector on its right to the vector on its left. For example,

LET vec1 = (1 2 3) & 4,6 & 7,10

is equivalent to

COPY (1 2 3) 4,6 7,10 vec1

In either case, vec1 becomes

vec1: (1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0)

Here's an example of invoking a user-defined subroutine in a LET command:

```'User-defined subroutine to convert'centigrade to fahrenheit.
NEWCMD C_TO_F temperaturesC temperaturesF
temperaturesF = temperaturesC * 1.8 + 32
END

'Program using subroutine in LET command:
DATA 5,50,5 temperaturesC
LET temperaturesF = C_TO_F(temperaturesC)
PRINT table temperaturesC temperaturesF
```

With this output:

```temperaturesC 	temperaturesF 5             	41
10            	50
15            	59
20            	68
25            	77
30            	86
35            	95
40            	104
45            	113
50            	122
```

If you don't like the long names of some of the commands, such as INTEGER_CEILING, you can write a short subroutine to invoke it with whatever name you like. For example:

```NEWCMD CEIL inVec outVec   INTEGER CEILING inVec outVec
END
```

This subroutine can then be used in a LET command like this:

`result = CEIL(vecA)`

Instead of this:

`result = INTEGER_CEILING(vecA)`