Programming


The Extensible Expression Evaluator

Like a calculator, only better and less irritating.

snapshot of the E3

Click on this link or on the E3 icon on the right side of the page to start the Extensible Expression Evaluator. It is fairly intuitive and has a built-in help system, so you can probably begin using it almost instantly. You must be using a CSS and Javascript-capable browser that is standards-compliant. Currently, this does not include Microsoft Internet Explorer, but does appear to include just about every other common browser. Firefox seems to provide the best and most consistent appearance and user experience. If your browser advises you that it has blocked a pop-up or script when you click on the link, click on the message and choose the option that permits the action to continue. The browser window that appears should be about 400 pixels wide and 600 pixels tall. If it opened in a full-size window or tab, you will find it convenient to resize the browser window to make it smaller. (Do this by clicking and dragging the bottom right corner of the window.) In some browsers, resizing even slightly may greatly improve the appearance of the evaluator. Your browser is displaying the evaluator correctly if the input field is in the dark red region at the bottom of the window, and if the output scrolls up from the bottom as you work.

I wrote the E3 out of frustration that no one else had already done so, and I find myself turning to it frequently when messing about with recipes, or brewing, or designing a shed, or pondering a random problem. Frequently too I think of cool new things it ought to be able to do, and on a good day I'll sit down and extend its capabilities. (I designed it to make this comparatively easy, hence the first "E" in E3. See Part 5 of the manual below.) I am keen to learn what extensions others might suggest. Also, although the list of bugs, ommissions, and other errors in the E3 is probably not Turing computable, a great many are likely to be human-detectable. I welcome your comments, suggestions, and corrections; please send them using the contact page.

If you would like to have the evaluator on your desktop without having to be online or come to this web site, or if you would like to tinker with it for fun or profit, you are welcome to do so. The entire set of files comprising the current version (including the manual below) is available as a zip file, e3.zip, under the GNU General Public License.

MANUAL

1. Introduction
2. Arithmetic
2.1 General
2.2 Order of Operations
2.3 Precision
2.4 Scientific Notation
3. Named Functions
3.1 Numeric (Number Theoretic) Functions
3.2 Combinatoric Functions
3.3 Statistical Functions
3.4 Transcendental Functions
3.5 Unit Conversion Functions
4. Named Constants
4.1 Previous Evaluations
4.2 Built-In Constants
4.3 User-Defined Constants
5. Extensions
5.1 Adding New Named Constants
5.2 Adding New Unit Conversions
5.3 Adding New Named Functions
6. Tips and Tricks

1. Introduction

The Extensible Expression Evaluator (hereinafter “ E3 ”) is a tool for performing practical calculations, and was designed for students and general users. It is written in html, css, and javascript, and runs well in most browsers. It requires no installation, and may be used as a web application either remotely or on a host machine. The entire set of files comprising E3 may be downloaded as a zip file: e3.zip. The files are distributed under the GNU General Public License, and may be freely distributed and modified. To run the E3 directly from the source files, open the file "E3_Manual.html" (which you are currently reading) and click on the indicated link to start the evaluator in its own window or tab. The E3 may be easily modified by anyone with a knowledge of html, css, and javascript. In particular it is simple to add custom functions and constants (hence the "extensible" in the name). See Section 5 for further information on extending the E3.

The E3 is called an expression evaluator rather than a calculator because it treats input as an ASCII string which it decomposes and modifies, and then uses regular expression pattern matching and a recursive algorithm to determine how to proceed with the evaluation. All expressions are converted to lower-case and all white space is removed before further evaluation. There are two kinds of output: floating-point and non-floating-point. The former is treated as “evaluated output” and is remembered for possible use in further calculations (see Section 4.1). Non-floating-point output includes error messages, comma-delimited lists (returned for example by the factor function), and other non-standard outputs such as the result of using the change-of-base function (Section 3.1). Enter ? in the E3 for basic help, and refer to this manual for more detailed information.

2. Arithmetic Calculations

2.1 General

To perform a calculation enter an arithmetic expression in the dark region at the bottom of the E3 window using standard notation. There is no fixed limit on the length of the expression that may be entered. Also, an expression may be copied from another source and pasted into the E3. Press [enter/return] to evaulate the expression. The expression entered will be immediately echoed directly above the input region flush with the left side of the window, and the evaluated output will appear in bold-face below the echoed input, but on the right side of the window. If the expression cannot be evaluated, an error message will appear as output. The general error message is “invalid entry,” but there are many particular error messages that may be triggered. For example, entering “((2+3)*2” will trigger the error message “unmatched parenthesis.”

The E3 recognizes the following operators:

a+b, the sum of a and b
a-b, the difference of a and b
a*b, the product of a and b
a/b, the result of dividing a by b
a^b, the result of raising a to the power b (exponentiation)
a%b, the remainder when a is divided by b (modular division)

To find square roots, cube roots, etc., use the exponentiation operator: entering “a^(1/n)” returns the principle nth root of a. For example, entering “2^(1/2)” will return 1.414213562373, the square root of 2 (to 12 decimal places). Currently, any expression of the form (-a)^b returns an error if b is not an integer, even if the value would properly be defined. For instance, (-1)^(1/3) returns an error rather than -1 as it should. The user will need to keep this in mind if the exponentiation operator is used with rational (non-integer) exponents.

2.2 Order of Operations

The E3 obeys the standard order of operations: It evaluates all named functions first, performs any modular division next, then exponentiation, and finally multiplication and division before addition and subtraction, which are both performed from left to right. Sub-expressions may be grouped with parentheses, and then expressions inside parentheses are evaluated first. The hyphen character “-” may be either the subtraction symbol or a negative sign. When used as a negative sign it must be grouped away from other operators with parentheses. For instance, both “-5+2 ” and “2+(-5)” will return the output “-3”, but “2+-5” will return an “invalid entry” error.

2.3 Precision

The E3 is not intended for high-precision computing. It uses javascript's built-in library of math methods to perform floating-point calculations, which retain up to 15 significant digits for each operation. However, to avoid certain kinds of errors, the E3 truncates output to no more than 12 decimal places in most instances. All significant digits but the last may be trusted in any simple calculation, but the final digit in some cases may not be properly rounded. Evaluated outputs larger than 10^15 or smaller than 10^(-6) may be returned using exponential (i.e., scientific) notation. (See the next sub-section.)

2.4 Scientific/Exponential Notation

Expressions of the form aen where a is a floating point number and n is an integer are said to be in exponential form, and are evaulated as a*10^n. Expressions and sub-expressions may be entered using exponential form, and evaluated outputs larger than 10^15 or smaller than 10^(-6) may be returned in exponential form. When entering expressions in exponential form with a negative exponent, do not group the negative exponent with parentheses. Entering “314159e-5” will return 3.14159 as expected, but “314159e(-5)” will return an error message. When using named constants for the base with exponential notation, group the constant name away from the ‘e’ with parentheses. Named constants may not be used for the exponent (use the ‘^’ notation instead).

3. Named Functions

Every named function is entered in the form [function name](arg(s)), where [function-name] is the name of the function and arg(s) is either a single expression or a comma-delimited list of expressions. Some functions require a fixed number of arguments of a given type. For example, the combinatoric function ncr(n,r) requires two arguments, each of which must evaluate to an integer, with the second not larger than the first. Most functions take a single argument, and in these cases the argument can be any expression that evaluates to a floating point number, including another function. Most named functions return a floating point number, but there are notable exceptions such as the change of base function and the factor function (see below for details).

3.1 Numeric (Number-Theoretic) Functions

base(arg,b1,b2) Converts arg from base b1 notation to base b2 notation. The bases b1 and b2 must be integers in the range 2 to 35. The argument arg must be a floating point number in base b1 notation. For bases greater than 10 use A as the numeral for 10, B as the numeral for 11, and so on. Note that arg is not evaluated, so you cannot, for instance, assign a base b1 number to a named constant and substitute the constant name for arg. Also, the output is not remembered as a calculated value, and so may not be referenced by the “prior output” constants p1, p2, etc. (Section 4.1). It is not uncommon for small rounding errors to occur with numbers having a decimal component.
factor(arg) Returns a comma-delimited list of all of the prime factors of arg, including repetitions. For example, factor(12) returns the output 2,2,3. Returns an error if arg does not evaluate to an integer. If arg is prime, it returns arg. When a list is returned, the output is not remembered as a calculated value. Owing to the limitations of javascript, errors are possible if arg evaluates to too large a number; consequently, arg will be rejected if it is not smaller than 1e15, i.e., ten to the fifteenth power.
gmean(arg1,...,argn) Returns the geometric mean of the evaluated arguments, i.e., the nth root of the product of the n factors. Every argument must evaluate to a floating point number.
sqrt(arg) Returns the square root of arg, which must evaluate to a positive number.

3.2 Combinatoric Functions

sum(arg1,...,argn) Returns the sum of the evaluated arguments, i.e., arg1 + arg2 + ... + argn.
product(arg1,...,argn) Returns the product of the evaluated arguments, i.e., arg1 * arg2 * ... * argn.
arg! Returns n factorial, i.e., 1 * 2 * ... * n, if arg evaluates to an integer n. The result is negative if n is negative. Returns an error if arg does not evaluate to an integer.
npr(arg1,arg2) Returns the number of ways to permute r objects from a collection of n objects, where arg1 evaluates to the integer n and arg2 evaluates to the integer r. Equivalent to n!/(n-r)!. The inputs may be any expressions that evaluate to integers, provided r is not greater than n.
ncr(arg1,arg2) Returns the number of ways to choose r objects from a collection of n objects without respect to order, where arg1 evaluates to the integer n and arg2 evaluates to the integer r. Equivalent to n!/(r!(n-r)!). The inputs may be any expressions that evaluate to integers, provided r is not greater than n.

3.3 Statistical Functions

count(arg1,...,argn) Returns n, the number of comma-delimited arguments. The arguments are not evaluated.
amean(arg1,...,argn) Returns the arithmetic mean of the evaluated arguments, i.e., their sum divided by n. Every argument must evaluate to a floating point number.
median(arg1,...,argn) Returns the median of the arguments. It does this by ordering the evaluations of the arguments numerically, then returning the middle value if there are an odd number of arguments and the average of the middle two values if there are an even number of arguments. Every argument must evaluate to a floating point number.
range(arg1,...,argn) Returns the difference of the largest and least values of the evaluated arguments. Every argument must evaluate to a floating point number.
stdev(arg1,...,argn) Returns the standard deviation of the evaluated arguments. Every argument must evaluate to a floating point number.

3.4 Transcendental Functions

sin(arg) Returns the sine of the evaluated argument. The argument must evaluate to a floating point number, and the unit of angle measure is radians. If the sine of an argment in degrees is desired, use the conversion function degtorad(arg) as the argument to sin.
cos(arg) Returns the cosine of the evaluated argument. The argument must evaluate to a floating point number, and the unit of angle measure is radians. If the cosine of an argment in degrees is desired, use the conversion function degtorad(arg) as the argument to cos.
tan(arg) Returns the tangent of the evaluated argument. The argument must evaluate to a floating point number, and the unit of angle measure is radians. If the tangent of an argment in degrees is desired, use the conversion function degtorad(arg) as the argument to tan.
asin(arg) Returns the arcsine (inverse sine) of the evaluated argument. The argument must evaluate to a floating point number in the range -1 to 1, and the value returned will be in the range -pi/2 to pi/2 radians. If an answer in degrees is desired, use the conversion function radtodeg(arg) on the value returned by asin.
acos(arg) Returns the arccosine (inverse cosine) of the evaluated argument. The argument must evaluate to a floating point number in the range -1 to 1, and the value returned will be in the range 0 to pi radians. If an answer in degrees is desired, use the conversion function radtodeg(arg) on the value returned by acos.
atan(arg) Returns the arctangent (inverse tangent) of the evaluated argument. The argument must evaluate to a floating point number, and the value returned will be in the range -pi/2 to pi/2 radians. If an answer in degrees is desired, use the conversion function radtodeg(arg) on the value returned by atan.
exp(arg) The standard exponential function; returns the natural number e raised to the power arg.
ln(arg) Returns the natural (base e) logarithm of the evaluated argument. The argument must evaluate to a non-negative floating point number. (Entering ln(0) will return -infinity.)
log(arg) Returns the common (base 10) logarithm of the evaluated argument. The argument must evaluate to a non-negative floating point number. (Entering log (0) will return -infinity.)
logb(arg,b) Returns the base b logarithm of the evaluated argument arg. The argument must evaluate to a non-negative floating point number, and the base must evaluate to a positive floating point number.

3.5 Unit Conversion Functions

All E3 conversion functions are of the form [unit1]to[unit2](arg), where unit1 and unit2 are abbreviations for units of the same type, as listed below. For example, to determine how many liquid ounces are in a gallon, enter galtooz(1). The argument must evaluate to a floating point number. Although these conversions amount to no more than multiplying arg by the appropriate conversion factor, the function notation was found to be desirable because it ensures that the names for these conversions do not conflict with names used for user-defined and built-in constants (Section 4), and in other ways makes parsing expressions less error prone. Conversions are precise to at least 4 significant digits. It is not difficult to add new conversion factors or even whole new types of unit conversions to the E3; see Section 5 for further information.

ANGLE
degDegrees of arc, where 360 degrees is one circle.
radRadians, where half a circle is pi radians.
gradGrads (also grade, gradians, or gons), where a grad is 1/400 of a circle.
secSeconds of arc, with 3600 seconds per circle.
minMinutes of arc, with 60 minutes per circle.
circOne full circle of arc.
 
LENGTH
mcMicrons (millionths of a meter).
mmMillimeters.
cmCentimeters.
mMeters.
kmKilometers.
inInches.
fFeet (standard).
yYards.
faFathoms (six feet).
fuFurlongs (eighth of a mile).
miMiles (statute).
nauNautical miles (international).
rodRods (5.5 yards).
 
AREA
cm2Square centimeters.
m2Square meters.
km2Square kilometers.
in2Square inches.
f2Square feet (standard).
y2Square yards.
mi2Square miles (statute).
 
VOLUME
ccCubic centimeters.
lLiters.
m3Cubic meters.
in3Cubic inches.
f3Cubic feet (standard).
y3Cubic yards.
tspTeaspoons (US liquid).
tbTablespoons (US liquid).
ozOunces (US fluid).
cupCups (US liquid).
pntPints (US liquid).
qrtQuarts (US liquid).
galGallons (US liquid).
galdGallons (US dry).
bushBushels (US).
peckPecks (US, fourth of a bushel).
brlBarrels (US liquid).
brldBarrels (US dry).
brlpBarrels (US petroleum).
 
MASS
mgMilligrams.
gGrams.
kgKilograms.
ozaOunces (avoirdupois).
lbPounds (avoirdupois).
tnTons (avoirdupois, equals 2,000 lbs).
tmTons (metric, equals 1,000 kilograms).
hwHundredweights.
drDrams.
grGrains.
pwPennyweights.
 
ENERGY
jJoules.
ergErgs.
btuBritish Thermal Units (ISO).
hphHorse-power hours.
ftlbfFoot-pound force.
calCalories.
kcalKilocalories (food calories).
kwhKilowatt hours.
 
FORCE
nNewton.
dynDyne.
kpKilopond, kilogram force.
lbfPound force.
pdlPoundal.
 
PRESSURE
paPascal.
barBar.
atTechnical atmosphere.
atmAtmosphere
trrTorr.
psiPound force per square inch.

4. Named Constants

The E3 uses both built-in and user-defined named constants. Constant names always begin with an alphabetic character, and contain only alphabetic and numeric characters. User-defined constants must be at least three characters in length. Constant names may be used in any expression in place of the value they represent. The values of built-in constants may not be reassigned by the user.

4.1 Previous Evaluations

The E3 maintains an array of named constants called p1, p2, ... , p25 that refer to the twenty-five most recently returned evaluations. The most recent evaluation is named p1, the next most recent p2, and so on. Non-numeric outputs are not counted in this numbering. For example, entering “2+2”, “2+-2”, “2*3”, and “p1-p2” in sequence will return the results “4”, “invalid entry”, “6”, and “2” respectively. The values of these constants are reset to 0 whenever the E3 is restarted.

4.2 Built-In Constants

MATH CONSTANTS
eNapier's constant, the ‘natural number’, also called Euler's number, assigned the approximate value 2.718281828459.
grThe golden ratio, assigned the approximate value 1.61803398875.
piThe ratio of the circumference of any circle to its diameter, assigned the approximate value 3.14159265359
 
PHYSICAL CONSTANTS
cThe approximate speed of light in a vacuum in meters-per-second, assigned the value 299792458.
gStandard Earth gravity in meters-per-second-per-second, assigned the value 9.80665.
 
CHEMICAL CONSTANTS
avAvogadro's number, assigned the value 6.0221415e+23.

4.3 User-Defined Constants

Users can create new, user-defined constants by entering an expression of the form [name]=value, where [name] begins with a letter, contains only letters and numbers, and is at least three characters long, and where value is any expression or comma-delimited list of expressions.

Once defined, the constant may be used in any expression in place of its value. This is especially convenient when the constant is assigned a long comma-delimited list as its value. For example, one might assign a list of data values to the constant name ‘oscar’ by entering “oscar = 34,56,43,72,39,88,42,57,45,62”. Subsequently entering stdev(oscar) will return the evaluation 15.898427595206, the standard deviation of the data.

The value assigned may also include the name of another constant. This allows for simple user-defined functions. For example, one might assign the value “length^2” to the name area. Whatever value is then assigned to the name length, the name area will represent the square of the value. Note that this only works with constants that evaluate to a single floating-point number. Assigning a name to a value that is itself the name of a comma-delimited list does not generally work out as one might wish.

You may delete a constant by assigning it an empty value. To see a list of all user-defined constants currently in memory, enter ?defconst. (Do this to see the actual values assigned to each constant name; merely entering the constant name itself returns the evaluation of this value, which may not be the same.) If the browser has cookies enabled, the user-defined constants are stored as cookies that last for one year. Consequently, one may define constants in one user-session and use the same constants in a future user-session, even if the browser application has been restarted or the computer itself turned off or rebooted. The cookie storing a constant name-value pair is deleted when the constant is deleted. Also, the expiration date of all stored cookies is automatically renewed each time the application is started. To find out if cookies are being stored by your browser, define a constant and then enter the word “cookies”. If you see the cookie storing your constant, cookies are enabled. Otherwise, use your browser's tools or options menu to permit cookies for the E3.

5. Extensions

Anyone with a knowledge of javascript will find it easy to extend the E3 by adding new constants, functions, or other functionality. The fundamental working principle of the E3 is that it evaluates string data by using regular expression matching, applying mathematical methods when needed, but always recasting any calculated results back into strings for further processing. The E3 also maintains a variable called errorMsg during processing. If the final result of an evaluation is not a floating point number (possibly in exponential notation), then errorMsg is returned instead. This is used not only to return tailored error messages, but also to display non-numeric evaluations when desired.

The E3 disassembles an input string into its atomic parts, recursively applying the operators and functions embedded within it. The order in which it does this must not be changed by any new extensions; consequently, extensions must be added to the code in the right locations. Refer to the instructions below for details.

5.1 Adding New Named Constants

To add new named constants, find the line in the javascript file mathparseandevaluate.js that has the comment “// CHECK FOR DEFINED CONSTANTS” and add the constant using the same syntax as the constants already defined. To avoid certain kinds of bugs, your new constant should contain only alphabetic characters. The constant must evaluate to a string, not a number, so if you use mathematical operations to define the value remember to recast the value to a string datatype (most easily done by concatenating the empty string). If you wish, you can add information about your constant to the E3 help system and this manual by editing the files help.js and E3_Manual.html.

5.2 Adding New Unit Conversions

To add new conversion factors for a unit of a type already available in the E3, it is only necessary to edit the E3.html file. Find the line in the javascript section with the comment “// CONVERSION FACTORS”, then locate the code for the unit type you wish to add the factor to. In the line defining the array “units[Type]” add the new unit to the comma delimited list in the form “[unit]|[factor]”, where [unit] is the name of the unit and [factor] is the conversion factor from the standard unit identified in the code comments to the unit you are adding. Save the file and test your unit by entering a conversion function that uses it.

To enter a new type of unit, you will need at least two units of the given type, and you will have to choose one unit as the standard. You will need to create a new block of code similar to the existing blocks for other unit types, naming the corresponding variables for the units array and the conversion-factors associative array. After completing these edits to E3.html, you will need to edit the file mathparseandevaluate.js. Find the line with the comment “// CONVERSIONS” and insert a new block of code in the same format as the blocks for the existing unit types, using the name of the global variable you defined in the “E3.html” file for the conversion-factors associative array. Once these steps are complete, you can test your new conversion type.

As always, you may wish to edit the help.js and E3_Manual.html files to provide information on your new conversion factors.

5.3 Adding New Named Functions

You must edit the file mathparseandevaluate.js to add new named functions, and only users with at least some experience writing javascript programs should attempt to do so. It is strongly recommended to examine this file carefully to see how other named functions have been defined. The code to match the pattern of new named functions must be added after the line with the comment “// CHECK FOR NAMED FUNCTIONS” and before the line with the comment “// ****** DO NOT ADD NEW NAMED FUNCTIONS AFTER THIS LINE!! ******”. Follow the pattern of the code for the existing functions. In particular, use regular-expression pattern-matching to match only atomic expressions of the form [function-name](arg), where [function-name] is the name of your new function and arg is the type of argument or comma-delimited list of arguments your function can accept, and use a javascript function call on the argument to return the evaluation. The function called (i.e., the javascript function that contains the code for your new named function) may be added at the end of the file. Except in unusual cases, your called function should immediately call the recursive function M(arg) on the argument to your named function (or on each of the arguments in a list) to evalute it. Cast the result of this evaluation to a numeric type to perform additional calculations, and remember to recast to a string type when the result is returned.

As always, you may wish to edit the help.js and E3_Manual.html files to provide information on your new functions.

6. Tips and Tricks

Because the E3 operates on text input and produces text output, there are a few tricks that can make using it more convenient.

  • If you have a large set of data, for example in a spreadsheet, you can save it to a comma-delimited text file (usually called a .cvs file), and then cut-and-paste the data directly into the E3 as the value of a named constant (See Section 4.3.) You don't need to worry about white space when you do this because the E3 automatically strips the white space from any input. You only need to ensure that the data is separated by commas.
  • You can use the “previous result” constants p1, p2, etc. to use old outputs in new calculations. However, you can also use a previous output by triple-clicking on the output to select the entire line (or click-drag to highlight it), and then either copy-and-paste it or simply drag it into the input window, inserting it anywhere in your new expression. You may do the same with previous inputs.
  • Reloading the E3 page resets the “previous result” constants p1, p2, etc. to 0. However, merely clearing the output area by entering the command clear does not reset these values.
  • Although the output of the E3 scrolls upward and eventually out of sight, it is actually all still on the web page until you type clear to clear the screen or restart the application by reloading the page. To access output that has scrolled out of sight in the browser window, click anywhere in the green area and “select all” from the context menu or by typing the appropriate keyboard combination, then copy it to the clipboard by again using the context menu or a keyboard shortcut. With the contents of the page on the clipboard you can paste it into a text-editor or word-processor. Alternatively, after selecting it, you can drag the contents of the E3 output window to such applications. In this way you can access (and save if you wish) and entire work session with the E3.