4.0. Introduction

Numbers and numeric operations in JavaScript are managed by two different JavaScript objects: `Number` and `Math`.

Like the `String` and `RegExp` objects discussed in earlier chapters, numbers can be both a literal value and an object. No surprises there, but the `Math` object is different: it has no constructor, and all properties and methods are accessed directly from the object.

The Number Object and Number Literal

Numbers in JavaScript are floating point, though there may not be a decimal component present. If no decimal is present, they act as if they’re integers:

`var someValue = 10; // treated as integer 10, in base 10`

Numbers can be defined in the range of –253 to 253. Most numbers in JavaScript are literal values, assigned as values to variables, and used in various computations:

```var myNum = 3.18;
var newNum = myNum * someValue;```

You can also construct a `Number` using a constructor method:

`var newNum = new Number(23);`

You can assign a literal number to a variable, but when you access a `Number` method on the variable, a `Number` object is created to wrap the literal value, which is discarded when the method is finished.

The `Number` object’s methods provide various display operations, such as providing an exponential notation:

```var tst = .0004532;

In addition, there are several static `Number` properties, which can only be accessed via the `Number` object directly:

`alert(Number.MAX_VALUE); // outputs 1.7976931348623157e+308`

There’s a special `Number` static property, `NaN`, which is equivalent to the global `NaN`, and stands for Not a Number. Anytime you try to use a value in a number operation that can’t be parsed as a number, you’ll get a `NaN` error:

```alert(parseInt("3.5")); // outputs 3
alert(parseInt("three point five")); // outputs NaN```

The Math Object

Unlike the `Number` object, the `Math` object does not have a constructor. All of the object’s functionality, its properties and methods, are static. If you try to instantiate a `Math` object:

`var newMath = new Math();`

You’ll get an error. Rather than create a new `Math` instance, access properties and methods directly on the object instead:

`var topValue = Math.max(firstValue, secondValue); // returns larger number`

The `Math` object has a considerable number of properties and methods, including several trigonometric methods. The precision of the methods is at the same level of precision that we would find using a language like C.

Table 4-1 provides a listing of the `Math` properties, and Table 4-2 contains a listing of the `Math` methods.

Table 4-1. Math object static properties
 Property Purpose E The number value for e, the base of natural logarithms LN2 Natural logarithm of 2 LN10 Natural logarithm of 10 LOG2E Base 2 logarithm of e, and the reciprocal of LN2 LOG10E Base 10 logarithm of e, and the reciprocal of LN10 PI The number for π SQRT1_2 Square root of 1/2, reciprocal of SQRT2 SQRT2 Square root of 2
Table 4-2. Math object static methods
 Method Purpose ```abs (x)``` Returns absolute value of `x`; if `x` is NaN, returns NaN ```acos (x)``` Returns arc cosine of `x`; if `x` is greater than 1 or less than 0, returns NaN ```asin (x)``` Returns arc sine of `x`; if `x` is greater than 1 or less than –1, returns NaN ```atan (x)``` Returns the arc tangent of `x` ```atan2 (x, y)``` Returns the arc tangent of the quotient of `x`, `y` ```ceil (x)``` Returns the smallest integer equal to or greater than `x` ```cos (x)``` Returns the cosine of `x` ```exp (x)``` Returns E`x` where E is the base of natural logarithms ```floor (x)``` Returns the largest integer equal to or less than `x` ```log (x)``` Returns logarithm of `x` ```max (x1, x2, ..., xn)``` Returns largest of given arguments ```min (x1, x2, ..., xn)``` Returns smallest of given arguments ```pow (x,y)``` Returns result of raising `x` to power of `y` ```random ()``` Returns random number greater than or equal to 0, and less than 1 ```round (x)``` Rounds number to closest integer ```sin (x)``` Returns the sine of `x` ```sqrt (x)``` Returns the square root of `x`

4.1. Keeping an Incremental Counter

Problem

You want to maintain an incremental counter in code.

Solution

Define a number variable, either locally or globally, or as part of an object’s properties, and increment the variable’s value with each iteration of code:

```var globalCounter = 0;
function nextTest() {
globalCounter++;
...
}```

Discussion

The simplest way to increase or decrease a number is using the increment (`++`) and decrement (`--`) operators, respectively. They’re equivalent to:

```numValue = numValue + 1; // equivalent to numValue++
numValue = numValue - 1; // equivalent to numValue--```

Both operators can be used prefix or postfix, which means the operators can be placed before or after the operand. How they’re positioned is significant. If the operator is placed before the operand, the operand’s value is adjusted first, before the operand is used:

```var numValue = 1;
var numValue2 = ++numValue; // numValue and numValue2 are both 2```

If the operator is postfix (placed after the operand), the operand is used first, and then its value is adjusted:

```var numValue = 1;
var numValue2 = numValue++; // numValue is 2 and numValue2 is 1```

The point at which the counter is incremented depends on its use. If it’s needed in a loop, the value is incremented in the loop:

```var counter = 0;
while (counter <= 10) {
...
counter++;
}```

If the counter is needed more globally, it can be declared as a global variable, but use with caution. A global variable is one that’s declared outside of a function, and isn’t redeclared within a function. It can easily conflict with any other global variables that might exist in the application or other libraries you use:

```var counter = 0;
function someFunction() {
counter++;
}```

Another approach is to add the counter as property to an object, persisting as long as the object, and accessible by all object methods.

Chapter 16 covers how to create JavaScript objects.

4.2. Converting a Decimal to a Hexadecimal Value

Problem

You have a decimal value, and need to find its hexadecimal equivalent.

Solution

Use the `Number` object’s `toString` method:

```var num = 255;

Discussion

By default, numbers in JavaScript are base 10, or decimal. However, they can also be created and used in hexadecimal and octal notation. Hexadecimal numbers begin with `0x` (a zero followed by lowercase x), and octal numbers always begin with zero:

```var octoNumber = 0255; // equivalent to 173 decimal
var hexaNumber = 0xad; // equivalent to 173 decimal```

Other base numbers can be created using the `Number` object’s `toString` method, passing in the base radix, in a range from 2 to 36:

```var decNum = 55;
var octNum = decNum.toString(8); // value of 67 octal
var hexNum = decNum.toString(16); // value of 37 hexadecimal
var binNum = decNum.toString(2); // value of 110111 binary```

To complete the octal and hexadecimal presentation, you’ll need to concatenate the zero to the octal, and the `0x` to the hexadecimal value.

Although decimals can be converted to any base number (between a range of 2 to 36), only the octal, hexadecimal, and decimal numbers can be manipulated, directly, as numbers.

The decimal to hexadecimal conversion is used in Recipe 4.4.

4.3. Creating a Random Number Generator

Problem

You need to generate a random number, between 0 and 255.

Solution

Use a combination of JavaScript `Math` methods: `random` to generate a random value between 0 and 1, which is then multiplied by 255, and `floor` to truncate the number.

`var randomNumber = Math.floor(Math.random() * 255);`

Discussion

The `random` method generates a random number between 0 and 1. To increase the range, multiply the result by the upper end of the range of values you want. If you need a random number with a higher lower end, such as a number between 5 and 10, multiply the value from `random` by a number equal to the upper range, minus the lower range, minus 1, and then add the lower range to the result:

`var randomNumber = Math.floor(Math.random() * 6) + 5;`

The `floor` method rounds down the floating-point value to the nearest integer.

4.4. Randomly Generating Colors

Problem

You need to randomly generate a web color.

Solution

Use the `Math` object to randomly generate each RGB (Red-Green-Blue) value:

```function randomVal(val) {
return Math.floor(Math.random() * val);
}

function randomColor() {
return "rgb(" + randomVal(255) + "," + randomVal(255) + "," +
randomVal(255) + ")";
}```

Discussion

Web color can be expressed either in hexadecimal notation, or as an RGB value. With the RGB value, each color is represented as a number between 0 and 255. The example demonstrates one technique to generate a color, using one function to randomly generate the number, and a second to return an RGB formatted string.

Older browsers may not support the RGB notation. To use a hexadecimal notation, the `randomColor` function can be altered to:

```function randomColor() {
// get red
var r = randomVal(255).toString(16);
if (r.length < 2) r= "0" + r;

// get green
var g = randomVal(255).toString(16);
if (g.length < 2) g= "0" + g;

// get blue
var b = randomVal(255).toString(16);
if (b.length < 2) b= "0" + b;

return "#" + r + g + b;
}```

The hexadecimal notation is used (`#ffffff`), and the generated decimal number is converted to hexadecimal notation, using the `Number` object’s `toString` method. Since a decimal value of something like zero converts to a single-digit character and the format needs to be double-digit, the length is tested and modified accordingly.

All the target browsers support both the RGB and hexadecimal notation, except IE7, which only supports hexadecimal.

See Recipe 4.1 about converting between decimal and hexadecimal notation, and Recipe 4.3 for how to randomly generate numbers.

4.5. Converting Strings in a Table to Numbers

Problem

You want to access values in an HTML table and convert to numbers for processing.

Solution

Access the numbers using the Document Object Model (DOM) API, and use the global function `parseInt` to convert the strings to number values:

``` var rows = document.getElementById("table1").children[0].rows;
var numArray = new Array();

for (var i = 0; i < rows.length; i++) {
numArray[numArray.length] = parseInt(rows[i].cells[1].firstChild.data);
}```

Discussion

The `parseInt` global function has two arguments: a required numeric string, and an optional radix (base). If the radix is not provided, it’s assumed to be 10, for decimal.

If the string provided doesn’t contain a number, `NaN` is returned. If the string contains a partial number, the parser will convert the number up to the point where a nonnumeric value is reached, and return the result:

```var numString = "133 hectares";
var numHectares = parseInt(numString); // returns 133```

If the number is in floating-point format, `parseInt` stops when it reaches the decimal, and returns just the integer part of the number. If the string could contain a floating-point number and you want the result to be a floating-point number, use the `parseFloat` global function, instead:

```var numString = "1.458 hectares";
var fltNum = parseFloat(numString); // returns 1.458```

4.6. Summing All Numbers in a Table Column

Problem

You want to traverse all of the values in a table column, convert the values to numbers, and then sum the values.

Solution

Traverse the table column containing numeric values, convert to numbers, and sum the numbers:

```var sum = 0;

// use querySelector to find all second table cells
var cells = document.querySelectorAll("td:nth-of-type(2)");

for (var i = 0; i < cells.length; i++)
sum+=parseFloat(cells[i].firstChild.data);```

Discussion

Both global functions `parseInt` and `parseFloat` convert strings to numbers, but `parseFloat` is more adaptable when it comes to handling numbers in an HTML table. Unless you’re absolutely certain all of the numbers will be integers, `parseFloat` can work with both integers and floating-point numbers.

As you traverse the HTML table and convert the table entries to numbers, sum the results. Once you have the sum, you can use it in a database update, print it to the page, or pop up a message box, as the solution demonstrates.

You can also add a sum row to the HTML table. Example 4-1 demonstrates how to convert and sum up numeric values in an HTML table, and then how to insert a table row with this sum, at the end. The code uses `document.querySelectorAll`, which uses a CSS selector, `td + td`. This selector finds all table cells that are preceded by another table cell.

Example 4-1. Converting table values to numbers and summing the results
```<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<title>Accessing numbers in table</title>

<script type="text/javascript">
//<![CDATA[

var sum = 0;

var dataTable = document.getElementById("table1");

// use querySelector to find all second table cells
var cells = document.querySelectorAll("td + td");

for (var i = 0; i < cells.length; i++)
sum+=parseFloat(cells[i].firstChild.data);

// now add sum to end of table
var newRow = document.createElement("tr");

// first cell
var firstCell = document.createElement("td");
var firstCellText = document.createTextNode("Sum:");
firstCell.appendChild(firstCellText);
newRow.appendChild(firstCell);

// second cell with sum
var secondCell = document.createElement("td");
var secondCellText = document.createTextNode(sum);
secondCell.appendChild(secondCellText);
newRow.appendChild(secondCell);

dataTable.appendChild(newRow);

}

//--><!]]>
</script>
<body>
<table id="table1">
<tr>
<td>Washington</td><td>145</td>
</tr>
<tr>
<td>Oregon</td><td>233</td>
</tr>
<tr>
<td>Missouri</td><td>833</td>
</tr>
</table>
</body>
</html>```

Being able to provide a sum or other operation on table data is helpful if you’re working with dynamic updates via an Ajax operation, such as accessing rows of data from a database. The Ajax operation may not be able to provide summary data, or you may not want to provide summary data until a web page reader chooses to do so. The users may want to manipulate the table results, and then push a button to perform the summing operation.

Table rows are simple to add, as long as you remember the steps:

1. Create a new table row using `document.createElement("tr")`.

2. Create each table row cell using `document.createElement("td")`.

3. Create each table row cell’s data using `document.createTextNode()`, passing in the text of the node (including numbers, which are automatically converted to a string).

4. Append the text node to the table cell.

5. Append the table cell to the table row.

6. Append the table row to the table. Rinse, repeat.

If you perform this operation frequently, you’ll most likely want to create functions for these operations, and package them into JavaScript libraries that you can reuse. Also, many of the available JavaScript libraries can do much of this work for you.

See more on JavaScript libraries in Chapter 17. View more demonstrations of creating web page components in Chapter 12. The `document.querySelectorAll` is one of the new Selectors API methods, and won’t work with older browsers. It is not supported in IE7. For new browsers, there may also be restrictions on its use. More examples and discussion of the Selectors API can be found in Recipe 11.4.

4.7. Converting Between Degrees and Radians

Problem

You have an angle in degrees. To use the value in the `Math` object’s trigonometric functions, you need to convert the degrees to radians.

Solution

To convert degrees to radians, multiply the value by (`Math.PI` / 180):

`var radians = degrees * (Math.PI / 180);`

To convert radians to degrees, multiply the value by (180 / `Math.PI`):

`var degrees = radians * (180 / Math.PI);`

Discussion

All `Math` trigonometric methods (`sin`, `cos`, `tin`, `asin`, `acos`, `atan`, and `atan2`), take values in radians, and return radians as a result. Yet it’s not unusual for people to provide values in degrees rather than radians, as degrees are the more familiar unit of measure. The functionality provided in the solution provides the conversion between the two units.

4.8. Find the Radius and Center of a Circle to Fit Within a Page Element

Problem

Given the width and height of a page element, you need to find the radius of the largest circle that fits within that page element, and its center point.

Solution

Find the smaller of the width and height; divide this by 2 to find the radius:

`var circleRadius = Math.min(elementWidth, elementHeight) / 2;`

Given the page element’s width and height, find the center by dividing both by 2:

```var x = elementWidth / 2;
var y = elementHeight / 2;```

Discussion

Working with graphics requires us to do things such as finding the center of an element, or finding the radius of the largest circle that will fit into a rectangle (or largest rectangle that can fit in a circle).

Example 4-2 demonstrates both of the solution calculations, modifying an SVG circle contained within an XHTML document so that the circle fits within the `div` element that surrounds it.

Example 4-2. Fitting a SVG circle into a div element
```<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<title>Using Math method to fit a circle</title>
<style type="text/css">
#elem
{
width: 400px;
height: 200px;
border: 1px solid #000;
}
</style>
<script type="text/javascript">
//<![CDATA[

function compStyle(elemId,property) {
var elem = document.getElementById(elemId);
var style;
if (window.getComputedStyle)
style=window.getComputedStyle(elem,null).getPropertyValue(property);
else if (elem.currentStyle)
style=elem.currentStyle[property];
return style;
}
var height = parseInt(compStyle("elem","height"));
var width = parseInt(compStyle("elem","width"));

var x = width / 2;
var y = height / 2;

var circleRadius = Math.min(width,height) / 2;

var circ = document.getElementById("circ");
circ.setAttribute("cx",x);
circ.setAttribute("cy",y);
}
//--><!]]>
</script>

<body>
<div id="elem">
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">
<circle id="circ" width="10" height="10" r="10" fill="red" />
</svg>

</div>
</body>```

Figure 4-1 shows the page once it’s loaded. There are techniques in SVG that can accomplish the same procedure using the SVG element’s `viewPort` setting, but even with these, at some point in time you’ll need to polish off your basic geometry skills if you want to work with graphics. However, as the example demonstrates, most of the math you’ll need is relatively simple, and basic.

Finding a circle’s radius and the center point of an element is important when working with both SVG and Canvas, covered in Chapter 15. The method used to find the computed width and height of the `div` element can be found in Recipe 13.2. Recipe 12.15 covers the `setAttribute` method.

SVG is not supported in IE8 and earlier, but should be supported in IE9.

4.9. Calculating the Length of a Circular Arc

Problem

Given the radius of a circle, and the angle of an arc in degrees, find the length of the arc.

Solution

Use `Math.PI` to convert degrees to radians, and use the result in a formula to find the length of the arc:

```// angle of arc is 120 degrees, radius of circle is 2
var radians = degrees * (Math.PI / 180);

Discussion

The length of a circular arc is found by multiplying the circle’s radius times the angle of the arc, in radians.

If the angle is given in degrees, you’ll need to convert the degree to radians first, before multiplying the angle by the radius.

The `Math` trigonometric methods provide essential functionality for creating various Canvas and SVG effects, discussed in Chapter 15. Recipe 4.7 covers how to convert between degrees and radians.