Sunday, February 19, 2006

JavaScript and Math
Blog Entry #30

d(f(x)) = ∫exsin2x dx
Today at reptile7's JavaScript blog we'll discuss advanced integration techniques - no, just kidding - but seriously, folks, we are going to talk about the intersection of mathematics and JavaScript as we look over HTML Goodies' JavaScript Primers #14, "Math Variables". JavaScript has a built-in Math object whose read-only properties provide numerical constants - e.g., Math.PI returns π, or 3.1415... - and whose methods can be used to carry out various mathematical operations - e.g., Math.sqrt(x) returns √x, or the square root of x. Rather oddly, Primer #14, notwithstanding its title, makes no mention of the JavaScript Math object (which is at least listed on the HTML Goodies JavaScript objects keyword reference page), and the math it does feature is simple in the extreme, so we will flesh things out a bit after we examine the Primer #14 Script, which is reproduced below:

<BODY>
<SCRIPT type="text/javascript">
var numsums = 10 + 2
alert("10 + 2 is " + numsums)
var x = 10
var y = x * 2
alert("10 X 2 = " + y)
var z = "Hello " + "Good Bye"
</SCRIPT>
</BODY>

Most of the issues that Joe takes up directly or indirectly in the "Deconstructing the Script" section of the primer we've covered previously.

• We introduced the role in JavaScript of the equals sign (=) as an assignment operator, by which the right side of the 'equation' is actively assigned to the left side, in Blog Entry #5. Perhaps I should state the concept here more 'melodramatically' to drive home the point that an equals sign in a JavaScript statement does not signify a passive condition of equality; rather, when you see:

some_entity_x = some_value_y;

the scriptwriter in effect is saying, "I hereby decree that y, as a value, is now assigned to x." This right-to-left reading of JavaScript statements is discussed in a recently posted "Understanding Operators" article at HTML Goodies.

• We discussed in Blog Entry #6 the use of a plus sign (+) as both an arithmetic addition operator and a concatenating string operator in the Primer #3 Script.

• We've been putting variables in the instance of the alert( ) method as far back as the Primer #9 Assignment.

• Joe revisits in some detail the topic of variables in JavaScript in the "Here's the Deal:" subsection of Primer #14 - indeed, the primer seems generally to be as much about variables as it is about math - and admittedly he does a better job here than he did back in Primer #6 ("Prompts & Variables"). (For those of you who prefer to get your information straight from the horse's mouth, the "Variables" section in Netscape's JavaScript 1.5 Core Guide is here; MSDN's "JScript Variables" page, to which I linked in Blog Entry #5 during my own discussion of JavaScript variables, is here.) One point of correction: variable statements do not need to have "[after the variable name] an equal sign, and a value." It's not at all uncommon to see JavaScript scripts begin with variable declarations of the form:

var variable_name;
/* more than one variable can be declared here: var variable_name_0, variable_name_1, variable_name_2, etc; */

The idea is to load the variable into the user's RAM in order to facilitate its subsequent use in the script, although I for my part suspect that such declarations are unnecessary more often than not.

Well, then, is there anything new here? Joe does introduce the - (short dash), * (asterisk), and / (solidus) characters as arithmetic operators for subtraction, multiplication, and division, respectively. Netscape notes that these (and the +) operators are not unique to JavaScript, but also appear in other programming languages.

Two more comments about two of the "Here's the Deal:" list items:

(1) "The value assigned to text variables must be surrounded by quotes. No quotes are allowed for numeric variables. If you do put quotes around a number, it becomes text with a numeric value of 0. YIKES!" On my computer, however, quoted numbers are not valuewise equivalent to 0 in arithmetic operations. In an addition, a quoted operand is simply concatenated; for example:

var eig = "6" + 2;
window.alert("6 plus 2 is: " + eig);

displays 6 plus 2 is: 62 (not 2 or 8) on the alert( ) box, when using either MSIE or Netscape. In a subtraction, multiplication, or division, a quoted operand is interpreted as a number (not a string) data type, and the calculation proceeds normally:

var thr = "6" / "2";
window.alert("6 divided by 2 is: " + thr);

displays 6 divided by 2 is: 3 on the alert( ) box. In sum, quotes are indeed "allowed" for numeric variables but are nonetheless unnecessary, even if you're concatenating a number with a text string, so leave them out.

(2) "All programming languages have Reserved Words and so does JavaScript. Any JavaScript book will list them. Using Reserved Words as variable names will cause errors. For example, using onMouseOver as a variable name is not a good idea." JavaScript's reserved words are listed in Appendix A of Netscape's JavaScript 1.5 Core Reference; "onMouseOver" isn't one of them, but we can make a larger point here: any of JavaScript's recognized keywords - including not only the reserved words but also those words that are used for JavaScript objects, properties, methods, and event handlers - are poor choices for variable names.

I use the word "poor" as I am not going to tell you that you can't get away with using some of these words for variable names some of the time - you can. Netscape won't allow you to use any of the reserved words for variable names ("Error: missing variable name") but MSIE will; for example, on my computer when using MSIE, var volatile = 4 * 8; window.alert(volatile); uneventfully pops up an alert( ) box displaying 32. Perhaps unsurprisingly, neither browser will let me use "window" for a variable name; however, my trial runs with "confirm", "fgColor", and yes, "onMouseOver" as variable names in simple examples all worked OK with both browsers. But in the name of writing unconfusing code and avoiding errors as often as possible, you should still steer clear of using JavaScript keywords for variable names.

At this point, you are in exasperation wondering, "When are we going to get to some real math?" Calm down, real math coming right up...

Some methods of the JavaScript Math object

Exponentiation

We can raise a number x to the "yth" power with the pow( ) method:

Math.pow(x,y); // Math.pow(2,5) returns 32 (25)

A separate exp( ) method exponentiates the constant e (2.718..., the base of the natural logarithm) to a given power:

Math.exp(x);

We can adapt the pow( ) method to finding the yth root of x, , by using a fractional second parameter; for example:

Math.pow(100,1/3);

returns the cube root of 100, or 4.641...

Also, square roots can be extracted by the sqrt( ) method, as noted earlier.

A quadratic equation of the form ax2 + bx + c = 0 has two roots, given by:

x = (-b ± (b2 - 4ac)½) ÷ 2a

We can easily write a script that accepts inputs for a, b, and c and solves the above for x. Consider the equation 3x2 + 9x - 30 = 0, whose roots are seen to be x = 2 and x = -5 by factoring it to (3x - 6)(x + 5) = 0. Plug 3, 9, and -30 into the appropriate boxes below, and then click (twice if necessary, depending on your browser) the "Solve it" button:

a: b: c:

Root #1: Root #2:

Here's my code in its original form (I had to modify it somewhat for the demo above in order to show its effect here at Blogger.com):

<form>
a: <input size="10"> b: <input size="10"> c: <input size="10"><p>
<input type="button" value="Solve it" onclick="qua( );"><p>
Root #1: <input size="10"> Root #2: <input size="10"><p>
<input type="reset">
</form>
<script type="text/javascript">
function qua( ) {
var a = document.forms[0].elements[0].value;
var b = document.forms[0].elements[1].value;
var c = document.forms[0].elements[2].value;
var b2 = Math.pow(b,2);
var d = 4*a*c;
var e = b2-d;
var f = Math.sqrt(e);
var r1 = (-b+f)/(2*a);
var r2 = (-b-f)/(2*a);
document.forms[0].elements[4].value = r1;
document.forms[0].elements[5].value = r2; }
</script>

Logarithms

The Math object has a log( ) method for obtaining the base-e natural logarithm of a number x:

Math.log(x); // returns ln x

It doesn't have a method for finding the base-10 common logarithm of a number, but it is simple enough to calculate a base-10 logarithm by dividing the natural logarithm by 2.303:

log10 x = (Math.log(x))/2.303;

Logarithmic calculations often involve very large or very small numbers, which are best expressed as "floating-point literals" using exponential notation as in the following example:

Express 529,000 = 5.29 × 105 as 5.29E5 (or 5.29e5)

Application: calculating the pH of a solution

What is the pH of 0.0035 M hydrochloric acid?

Recall from general chemistry that pH = -log10 [H3O+] and that hydrogen chloride dissociates to give hydronium (H3O+) and chloride (Cl-) ions quantitatively in aqueous solution. So, for 0.0035 M HCl, [H3O+] = 0.0035 M, and:

var pH = -(Math.log(3.5E-3))/2.303; // this gives pH = 2.455...
document.write("The pH of 0.0035 M HCl is: " + pH);

Trigonometry

Ah, we wouldn't want to leave out the trig fans in the audience...the Math object has methods for the following three basic trigonometric functions:

For sine: Math.sin(x);
For cosine: Math.cos(x);
For tangent: Math.tan(x);

Taking reciprocals of the above gives methods for the cosecant (1/Math.sin(x)), secant (1/Math.cos(x)), and cotangent (1/Math.tan(x)) functions.

For these methods, the inputted angle must be in units of radians (not degrees), where a 1-radian angle ≅ 57.3°. For example, if you want to calculate the cosine of a 60° angle, the code would be:

var sixty = Math.cos(Math.PI/3);
// as noted above, Math.PI returns π; 60° = π/3 radians

The Math object also has methods for the 'inverse' arc sine (Math.asin(x);), arc cosine (Math.acos(x);), and arc tangent (Math.atan(x);) functions that output angle values, in radians, corresponding to an inputted length ratio x.

Calculus

As far as I am aware, there are no calculus-related Math object methods, and as I recall, I told you that calculus isn't my forte anyway. But as an exercise, you should now be able to write a script for differentiating a polynomial function of the form f(x) = axn + bxn-1 + cxn-2 + ..., given that d(xn) = nxn-1 dx and d(u(x) + v(x)) = (du(x)/dx + dv(x)/dx) dx.

Handling data and the JavaScript Number object

My demos in this post return in most cases numbers that trail many digits past the decimal point, and my guess is that you probably don't want that; fortunately, JavaScript has a built-in Number object having two methods, toFixed( ) and toPrecision( ), that are useful for expressing a number with a given number of significant figures. As illustrated in JavaScript Kit's "Formatting numbers for decimals and significant digits in JavaScript" tutorial, the toFixed( ) method sets a specific number of digits after the decimal point, whereas the toPrecision( ) method sets a total number of significant figures; for example:

(-(Math.log(3.5E-3))/2.303).toFixed(2) returns: 2.46
(Not quite as unwieldy as 2.4554894965205247, eh? Note that the digit in the hundredths place is rounded up.)

(Math.cos(Math.PI/3)).toPrecision(3) returns: 0.500
(The 'cosmetic' 0 to the left of the decimal point is not a significant digit.)

I think that's enough math for the time being. In the next entry, we'll return to the topic of images as we check out HTML Goodies' JavaScript Primers #15 and get our first taste of the "image flip" process briefly mentioned in Blog Entry #15.

reptile7