This chapter will focus on JavaScript number operations, number representation, Number objects, common number algorithms, and random number generation. By the end of this chapter, you will understand how to work with numbers in JavaScript as well as how to implement prime factorization, which is fundamental for encryption.
These operators are universally used in other programming languages and are not specific to JavaScript.
Number System

The 32-bit floating-point number system

Figure 3-1 shows the following break down of the 32 bits:
sign = 0

This results in the following:
value = 1 x 2124-127 x 1.25 = 1 x 2-3 x 1.25 = 0.15625
With decimal fractions, this floating-point number system causes some rounding errors in JavaScript. For example, 0.1 and 0.2 cannot be represented precisely.
To really understand why 0.1 cannot be represented properly as a 32-bit floating-point number, you must understand binary. Representing many decimals in binary requires an infinite number of digits. This because binary numbers are represented by 2n where n is an integer.

Long division for 0.1
JavaScript Number Object
Luckily, there are some built-in properties of the Number object in JavaScript that help work around this.
Integer Rounding
Since JavaScript uses floating point to represent all numbers, integer division does not work.
Integer division in programming languages like Java simply evaluates division expressions to their quotient.
Number.EPSILON
This function works by checking whether the difference between the two numbers are smaller than Number.EPSILON. Remember that Number.EPSILON is the smallest difference between two representable numbers. The difference between 0.1+0.2 and 0.3 will be smaller than Number.EPSILON.
Maximums
Number.MAX_VALUE returns the largest floating-point number possible.
Minimums
Number.MIN_SAFE_INTEGER returns the smallest integer.
Number.MIN_VALUE returns the smallest floating-point number possible.
Number.MIN_VALUE is equal to 5e-324. This is not a negative number since it is the smallest floating-point number possible and means that Number.MIN_VALUE is actually bigger than Number.MIN_- SAFE_INTEGER.
This is because this is similar to writing 0 - 1 == -1.
Infinity
This evaluates to true because nothing can go smaller than -Infinity.
Size Summary
Number Algorithms
One of the most discussed algorithms involving numbers is for testing whether a number is a prime number. Let’s review this now.
Primality Test
Time Complexity: O(n)
The time complexity is O(n) because this algorithm checks all numbers from 0 to n.
This is an example of an algorithm that can be easily improved. Think about how this method iterates through 2 to n. Is it possible to find a pattern and make the algorithm faster? First, any multiple of 2s can be ignored, but there is more optimization possible.
Time Complexity: O(sqrt(n))
This improved solution cuts the time complexity down significantly.
Prime Factorization
Time Complexity: O(sqrt(n))
This algorithm works by printing any number that is divisible by i without a remainder. In the case that a prime number is passed into this function, it would be handled by printing whether n is greater than 2.
Random Number Generator
Math.random() returns a float between 0 and 1.
You may wonder how you get random integers or numbers greater than 1.
Exercises
- 1.
Given three numbers x, y, and p, compute (xˆy) % p. (This is modular exponentiation.)
Here, x is the base, y is exponent, and p is the modulus.
Modular exponentiation is a type of exponentiation performed over a modulus, which is useful in computer science and used in the field of public-key encryption algorithms.
At first, this problem seems simple. Calculating this is a one-line solution, as shown here:1 function modularExponentiation ( base, exponent, modulus ) {2 return Math.pow(base,exponent) % modulus;3 }This does exactly what the question asks. However, it cannot handle large exponents.
Remember that this is implemented with encryption algorithms. In strong cryptography, the base is often at least 256 bit (78 digits).
Consider this case, for example:
Base: 6x1077, Exponent: 27, Modulus: 497
In this case, (6x1077)27 is a very large number and cannot be stored in a 32-bit floating point.
There is another approach, which involves some math. One must observe the following mathematical property:
For arbitrary a and b,c % m = (a b) % mc % m = [(a % m) (b % m)] % mUsing this mathematical property, you can iterate 1 to the exponent, recalculating each time by multiplying the current modulus value with the last.
Here is the pseudocode:1 Set value = 1, current exponent = 0.2 Increment current exponent by 1.3 Set value = (base value) mod modulus until current exponent is reached exponentExample: Base: 4, Exponent: 3, Modulus: 5
4ˆ3 % 5 = 64 % 5 = 4
value = (lastValue x base ) % modulus:
value = (1 x 4) % 5 = 4 % 5 = 4
value = (4 x 4) % 5 = 16 % 5 = 1
value = (1 x 4) % 5 = 4 % 5 = 4
Finally, here is the code:1 function modularExponentiation ( base, exponent, modulus ) {2 if (modulus == 1) return 0;34 var value = 1;56 for ( var i=0; i<exponent; i++ ){7 value = (value * base) % modulus;8 }9 return value;10 }Time Complexity: O(n)
The time complexity is O(n) where n is equal to the exponent value.
- 2.
Print all primes less than n.
To do this, use the isPrime function covered in this chapter. Simply iterate from 0 to n and print any prime numbers where isPrime() evaluates to true.1 function allPrimesLessThanN(n){2 for (var i=0; i<n; i++) {3 if (isPrime(i)){4 console.log(i);5 }6 }7 }89 function isPrime(n){10 if (n <= 1) return false;11 if (n <= 3) return true;1213 // This is checked so that we can skip14 // middle five numbers in below loop15 if (n%2 == 0 || n%3 == 0) return false;1617 for (var i=5; i*i<=n; i=i+6){18 if (n%i == 0 || n%(i+2) == 0)19 return false;20 }2122 return true;23 }2425 allPrimesLessThanN(15);2627 // prints 2, 3, 5, 7, 11, 13Time Complexity: O(nsqrt(n))
This is because isPrime (covered earlier in this chapter) with a time complexity of O(sqrt(n)) is run n times.
- 3.
Check for a set of prime factors.
Let’s define ugly numbers as those whose only prime factors are 2, 3, or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, … shows the first 11 ugly numbers. By convention, 1 is included.
To do this, divide the number by the divisors (2, 3, 5) until it cannot be divided without a remainder. If the number can be divided by all the divisors, it should be 1 after dividing everything.1 function maxDivide (number, divisor) {2 while (number % divisor == 0) {3 number /= divisor;4 }5 return number;6 }78 function isUgly (number){9 number = maxDivide(number, 2);10 number = maxDivide(number, 3);11 number = maxDivide(number, 5);12 return number === 1;13 }Iterate this over n, and now the list of ugly numbers can be returned.1 function arrayNUglyNumbers (n) {2 var counter = 0, currentNumber = 1, uglyNumbers = [];34 while ( counter != n ) {56 if ( isUgly(currentNumber) ) {7 counter++;8 uglyNumbers.push(currentNumber);9 }1011 currentNumber++;12 }1314 return uglyNumbers;15 }
Time Complexity for maxDivide(number, divisor): O(logdivisor(number))
The time complexity of maxDivide is a logarithmic function which depends on divisor and the number. When testing primes of 2, 3, and 5, the logarithmic of 2 (log2 (n)) yields the highest time complexity.
Time Complexity for isUgly: O(log2(n))
Time Complexity for arrayNUglyNumbers: O(n(log2(n)))
The isUgly function is limited by the time complexity of maxDivide(number, 2). Hence, arrayNUglyNumbers has n times that time complexity.
Summary
Prime number validation and prime factorization are concepts used in various computer science applications such as encryption, as covered in Chapter 4. Finally, random number generation in JavaScript works via Math.random().