Join the DZone community and get the full member experience.Join For Free
Displaying decimal numbers
Fixed notation versus exponential notation
[ "+" | "-" ] digit+ [ "." digit+ ]
and exponential notation
[ "+" | "-" ] digit [ "." digit+ ] "e" [ "+" | "-" ] digit+
An example of exponential notation is -1.37e+2. For output, there is always exactly one digit before the point, for input you can use more than one digit. Exponential notation is interpreted as follows: Given a number in exponential notation
significand e exponent
The value of that number is
significand × 10exponent
Hence, -1.37e+2 represents the number −137.
Displaying decimal numbers
The rules for displaying numbers are can be summarized as follows:
Use exponential notation if there are more than 21 digits before the decimal point. Example:
> 1234567890123456789012 1.2345678901234568e+21 > 123456789012345678901 123456789012345680000
Use exponential notation if number starts with “0.” followed by more than five zeros. Example:
> 0.0000003 3e-7 > 0.000003 0.000003
Otherwise, use fixed notation.
Read on if you want to know more about how displaying numbers is specified.
The ECMAScript 5.1 display algorithm in detail
Sect. 9.8.1 of the ECMAScript 5.1 specification describes the algorithm for displaying a decimal number. This section explains it. We first need to make a few preliminary definitions.
The mantissa of a floating point number is an integer – the significant digits plus a sign. Leading and trailing zeros are discarded. Examples:
- The mantissa of 12.34 is 1234.
- The mantissa of 0.00045 is 45
- The mantissa of 1000 is 1
- The mantissa of −27 is −27
The general idea is that you only need integers if you store a floating point number as a pair (mantissa, exponent), to be interpreted like this:
mantissa × 10exponent
The ECMAScript specification varies this idea by expressing a number as
mantissa × 10pointPos−digitCount
Hence, the previous exponent is now pointPos−digitCount. digitCount denotes the “length” of the mantissa, the number of digits that it has. Based on that definition, pointPos works as follows.
pointPos = 0: point is before the digits.
> 123 * Math.pow(10, 0 - 3) 0.123
pointPos ≥ 1: point is after the 1st (2nd, etc.) digit. If pointPos is less than digitCount then then the point appears “inside” the mantissa:
> 123 * Math.pow(10, 1 - 3) 1.23
If pointPos is the same as digitCount then the point appears after the last digit of the mantissa.
> 123 * Math.pow(10, 3 - 3) 123
If pointPos is greater than digitCount then zeros are inserted after the mantissa and before the point.
> 123 * Math.pow(10, 5 - 3) 12300
- pointPos ≤ −1: one (two, etc.) zeros appear after the point and before the mantissa.
> 123 * Math.pow(10, -2 - 3) 0.00123
Given a number
mantissa × 10pointPos−digitCount
The algorithm has four main cases (here, the last case merges the actual algorithm’s last two cases).
No decimal point: digitCount ≤ pointPos ≤ 21
Print the digits (without leading zeros), followed by pointPos−digitCount zeros.
Decimal point inside the mantissa: 0 < pointPos ≤ 21, pointPos < digitCount
Display the pointPos first digits of the mantissa, a point and then the remaining digitCount−pointPos digits.
Decimal point comes before the mantissa: −6 < pointPos ≤ 0
Display a 0 followed by a point, −pointPos zeros and the mantissa.
Exponential notation: pointPos ≤ -6 or pointPos > 21
Display the first digit of the mantissa. If there are more digits then display a point and the remaining digits. Next, display the character e and a plus or minus sign (depending on the sign of pointPos−1), followed by the absolute value of pointPos−1. Therefore, the result looks as follows.
mantissa0 [ "." mantissa1..digitCount ]
"e" signChar(pointPos−1) abs(pointPos−1)
Methods for converting numbers to string
This conversion is usually a preliminary step for displaying a number: Convert the number to a string that “looks” as desired and then show it somewhere.
The parameter radix indicates the base of the system in which the number is to be displayed. The most common radices are 10 (decimal), 2 (binary) and 16 (hexadecimal).
> 15..toString(2) '1111' > 65535..toString(16) 'ffff'
The radix must be at least 2 and at most 36. Any radix greater than 10 leads to alphabetical characters being used as digits, which explains the maximum 36, as the latin alphabet has 26 characters.
> 1234567890..toString(36) 'kf12oi'
The global function parseInt allows you to convert such notations back to a number:
> parseInt('kf12oi', 36) 1234567890
If the radix is 10, the algorithm from Sect. 1 is used to convert the number to a string.
This method forces a number to be expressed in exponential notation. fractionDigits is a number between 0 and 20 that determines how many digits should be shown after the decimal point. If it is omitted then “include as many significand [mantissa] digits as necessary to uniquely specify the Number” (ECMAScript 5.1 specification, Sect. 126.96.36.199). The following are a few examples.
Force more precision when toString() would also use exponential notation. Results are mixed, because one reaches the limits of the precision that can be achieved when converting binary numbers to a decimal notation.
> 1234567890123456789012..toString() '1.2345678901234568e+21' > 1234567890123456789012..toExponential(20) '1.23456789012345677414e+21'
Get exponential notation when numbers are not large enough.
> 1234..toString() '1234' > 1234..toExponential(5) '1.23400e+3' > 1234..toExponential() '1.234e+3'
Get exponential notation when non-zero numbers are not small enough.
> 0.003.toString() '0.003' > 0.003.toExponential(4) '3.0000e-3' > 0.003.toExponential() '3e-3'
Number.prototype.toFixed(fractionDigits?)If the number is greater than 1021 then this method is the same as toString(). Thus, you are not guaranteed to not get a number in exponential notation.
> 1234567890123456789012..toFixed() '1.2345678901234568e+21' > 1234567890123456789012..toString() '1.2345678901234568e+21'Otherwise, you will get a fixed point representation of the number, rounded to fractionDigits digits. If the parameter is omitted, the value 0 is used.
> 0.0000003.toFixed(10) '0.0000003000' > 0.0000003.toString() '3e-7'
Number.prototype.toPrecision(precision?)This method prunes the mantissa to precision digits, before using a conversion algorithm similar to toString(). If no precision is given, toString() is used directly.
> 1234..toPrecision(3) '1.23e+3' > 1234..toPrecision(4) '1234' > 1234..toPrecision(5) '1234.0' > 1.234.toPrecision(3) '1.23'Obviously, you need the exponential notation to display 1234 with a precision of 3 digits.
It is interesting to note that you can always append ex to a number and it will be multiplied by 10x.
> 123e3 123000 > 123e-3 0.123
Published at DZone with permission of Axel Rauschmayer, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.