JavaScript – Numbers

Unlike many languages, JavaScript does not make a distinction
between integer values and floating-point values. All numbers in
JavaScript are represented as floating-point values. JavaScript
represents numbers using the 64-bit floating-point format defined by
the IEEE 754 standard,[1] which means it can represent numbers as large as
±1.7976931348623157 × 10308 and as small as
±5 × 10−324.

The JavaScript number format allows you to exactly represent all
integers between −9007199254740992 (−253)
and 9007199254740992 (253), inclusive. If
you use integer values larger than this, you may lose precision in the
trailing digits. Note, however, that certain operations in JavaScript
(such as array indexing and the bitwise operators described in Chapter 4) are performed with 32-bit integers.

When a number appears directly in a JavaScript program, it’s
called a numeric literal. JavaScript supports
numeric literals in several formats, as described in the following
sections. Note that any numeric literal can be preceded by a minus
sign (-) to make the number negative. Technically, however, – is the
unary negation operator (see Chapter 4) and is
not part of the numeric literal syntax.

Integer Literals

In a JavaScript program, a base-10 integer is written as a
sequence of digits. For example:

0
3
10000000

In addition to base-10 integer literals, JavaScript recognizes
hexadecimal (base-16) values. A hexadecimal literal begins with “0x”
or “0X”, followed by a string of hexadecimal digits. A hexadecimal
digit is one of the digits 0 through 9 or the letters a (or A)
through f (or F), which represent values 10 through 15. Here are
examples of hexadecimal integer literals:

0xff  // 15*16 + 15 = 255 (base 10)
0xCAFE911

Although the ECMAScript standard does not support them, some
implementations of JavaScript allow you to specify integer literals
in octal (base-8) format. An octal literal begins with the digit 0
and is followed by a sequence of digits, each between 0 and 7. For
example:

0377  // 3*64 + 7*8 + 7 = 255 (base 10)

Since some implementations support octal literals and some do
not, you should never write an integer literal with a leading zero;
you cannot know in this case whether an implementation will
interpret it as an octal or decimal value. In the strict mode of
ECMAScript 5 (“use strict”), octal literals are
explicitly forbidden.

Floating-Point Literals

Floating-point literals can have a decimal point; they use the
traditional syntax for real numbers. A real value is represented as
the integral part of the number, followed by a decimal point and the
fractional part of the number.

Floating-point literals may also be represented using
exponential notation: a real number followed by the letter e (or E),
followed by an optional plus or minus sign, followed by an integer
exponent. This notation represents the real number multiplied by 10
to the power of the exponent.

More succinctly, the syntax is:

[digits][.digits][(E|e)[(+|-)]digits]

For example:

3.14
2345.789
.333333333333333333
6.02e23        // 6.02 × 10^23
1.4738223E-32  // 1.4738223 × 10^−32

Arithmetic in JavaScript

JavaScript programs work with numbers using the arithmetic
operators that the language provides. These include + for addition, - for subtraction, * for multiplication, /
for division, and % for
modulo (remainder after division). Full details on these and other
operators can be found in Chapter 4.

In addition to these basic arithmetic operators, JavaScript
supports more complex mathematical operations through a set of
functions and constants defined as properties of the Math object:

Math.pow(2,53)           // => 9007199254740992: 2 to the power 53
Math.round(.6)           // => 1.0: round to the nearest integer
Math.ceil(.6)            // => 1.0: round up to an integer
Math.floor(.6)           // => 0.0: round down to an integer
Math.abs(-5)             // => 5: absolute value
Math.max(x,y,z)          // Return the largest argument
Math.min(x,y,z)          // Return the smallest argument
Math.random()            // Pseudo-random number x where 0 <= x < 1.0
Math.PI                  // π: circumference of a circle / diameter
Math.E                   // e: The base of the natural logarithm
Math.sqrt(3)             // The square root of 3
Math.pow(3, 1/3)         // The cube root of 3
Math.sin(0)              // Trigonometry: also Math.cos, Math.atan, etc.
Math.log(10)             // Natural logarithm of 10
Math.log(100)/Math.LN10  // Base 10 logarithm of 100
Math.log(512)/Math.LN2   // Base 2 logarithm of 512
Math.exp(3)              // Math.E cubed

See the Math object in the reference section for complete
details on all the mathematical functions supported by
JavaScript.

Arithmetic in JavaScript does not raise errors in cases of
overflow, underflow, or division by zero. When the result of a
numeric operation is larger than the largest representable number
(overflow), the result is a special infinity value, which JavaScript
prints as Infinity. Similarly,
when a negative value becomes larger than the largest representable
negative number, the result is negative infinity, printed as
-Infinity. The infinite values
behave as you would expect: adding, subtracting, multiplying, or
dividing them by anything results in an infinite value (possibly
with the sign reversed).

Underflow occurs when the result of a numeric operation is
closer to zero than the smallest representable number. In this case,
JavaScript returns 0. If underflow occurs from a negative number,
JavaScript returns a special value known as “negative zero.” This
value is almost completely indistinguishable from regular zero and
JavaScript programmers rarely need to detect it.

Division by zero is not an error in JavaScript: it simply
returns infinity or negative infinity. There is one exception,
however: zero divided by zero does not have a well-defined value,
and the result of this operation is the special not-a-number value,
printed as NaN. NaN also arises if you attempt to divide
infinity by infinity, or take the square root of a negative number
or use arithmetic operators with non-numeric operands that cannot be
converted to numbers.

JavaScript predefines global variables Infinity and NaN to hold the positive infinity and
not-a-number value. In ECMAScript 3, these are read/write values and
can be changed. ECMAScript 5 corrects this and makes the values
read-only. The Number object
defines alternatives that are read-only even in ECMAScript 3. Here
are some examples:

Infinity                    // A read/write variable initialized to Infinity.
Number.POSITIVE_INFINITY    // Same value, read-only.
1/0                         // This is also the same value.
Number.MAX_VALUE + 1        // This also evaluates to Infinity.

Number.NEGATIVE_INFINITY    // These expressions are negative infinity.
-Infinity
-1/0                        
-Number.MAX_VALUE - 1

NaN                         // A read/write variable initialized to NaN.
Number.NaN                  // A read-only property holding the same value.
0/0                         // Evaluates to NaN.

Number.MIN_VALUE/2          // Underflow: evaluates to 0
-Number.MIN_VALUE/2         // Negative zero
-1/Infinity                 // Also negative 0
-0

The not-a-number value has one unusual feature in JavaScript:
it does not compare equal to any other value, including itself. This
means that you can’t write x ==
NaN
to determine whether the value of a variable x is NaN. Instead, you should write x != x. That expression will be true if,
and only if, x is NaN. The
function isNaN() is similar. It
returns true if its argument is
NaN, or if that argument is a
non-numeric value such as a string or an object. The related
function isFinite() returns
true if its argument is a number
other than NaN, Infinity, or – Infinity.

The negative zero value is also somewhat unusual. It compares
equal (even using JavaScript’s strict equality test) to positive
zero, which means that the two values are almost indistinguishable,
except when used as a divisor:

var zero = 0;         // Regular zero
var negz = -0;        // Negative zero
zero === negz         // => true: zero and negative zero are equal 
1/zero === 1/negz     // => false: infinity and -infinity are not equal

Binary Floating-Point and Rounding Errors

There are infinitely many real numbers, but only a finite
number of them (18437736874454810627, to be exact) can be
represented exactly by the JavaScript floating-point format. This
means that when you’re working with real numbers in JavaScript, the
representation of the number will often be an approximation of the
actual number.

The IEEE-754 floating-point representation used by JavaScript
(and just about every other modern programming language) is a binary
representation, which can exactly represent fractions like 1/2, 1/8, and 1/1024. Unfortunately, the fractions we
use most commonly (especially when performing financial
calculations) are decimal fractions 1/10, 1/100, and so on. Binary floating-point
representations cannot exactly represent numbers as simple as
0.1.

JavaScript numbers have plenty of precision and can
approximate 0.1 very closely. But
the fact that this number cannot be represented exactly can lead to
problems. Consider this code:

var x = .3 - .2;    // thirty cents minus 20 cents
var y = .2 - .1;    // twenty cents minus 10 cents
x == y              // => false: the two values are not the same!
x == .1             // => false: .3-.2 is not equal to .1
y == .1             // => true: .2-.1 is equal to .1

Because of rounding error, the difference between the
approximations of .3 and .2 is not exactly the same as the
difference between the approximations of .2 and .1. It is important
to understand that this problem is not specific to JavaScript: it
affects any programming language that uses binary floating-point
numbers. Also, note that the values x and y
in the code above are very close to each other
and to the correct value. The computed values are adequate for
almost any purpose: the problem arises when we attempt to compare
values for equality.

A future version of JavaScript may support a decimal numeric
type that avoids these rounding issues. Until then you might want to
perform critical financial calculations using scaled integers. For
example, you might manipulate monetary values as integer cents
rather than fractional dollars.

Dates and Times

Core JavaScript includes a Date() constructor for creating objects
that represent dates and times. These Date objects have methods that
provide an API for simple date computations. Date objects are not a
fundamental type like numbers are. This section presents a quick
tutorial on working with dates. Full details can be found in the
reference section:

var then = new Date(2010, 0, 1);  // The 1st day of the 1st month of 2010
var later = new Date(2010, 0, 1,  // Same day, at 5:10:30pm, local time
                     17, 10, 30);
var now = new Date();          // The current date and time
var elapsed = now - then;      // Date subtraction: interval in milliseconds 

later.getFullYear()            // => 2010
later.getMonth()               // => 0: zero-based months
later.getDate()                // => 1: one-based days
later.getDay()                 // => 5: day of week.  0 is Sunday 5 is Friday.
later.getHours()               // => 17: 5pm, local time
later.getUTCHours()            // hours in UTC time; depends on timezone

later.toString()               // => "Fri Jan 01 2010 17:10:30 GMT-0800 (PST)"
later.toUTCString()            // => "Sat, 02 Jan 2010 01:10:30 GMT"
later.toLocaleDateString()     // => "01/01/2010"
later.toLocaleTimeString()     // => "05:10:30 PM"
later.toISOString()            // => "2010-01-02T01:10:30.000Z"; ES5 only


[1] This format should be familiar to Java programmers as the
format of the double type. It
is also the double format used
in almost all modern implementations of C and C++.

Comments are closed.