Number Representations & States

"how numbers are stored and used in computers"

Prime Numbers

Prime numbers are a fundamental concept in number theory, and they have been studied extensively for centuries. A prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself. In other words, a prime number is a positive integer that is only divisible by 1 and itself.

Is one prime?

The number one is not considered a prime number.

By definition, a prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself. Since one only has one positive divisor, which is itself, it does not meet the criteria of having exactly two distinct positive divisors.

This distinction is important in number theory, as it helps maintain the Fundamental Theorem of Arithmetic, which states that every integer greater than is either a prime number or can be uniquely factored into prime numbers. Including as a prime would disrupt this unique factorization property.

Sieve of Eratosthenes

The Sieve of Eratosthenes is an efficient algorithm for finding all prime numbers up to a given limit. It works by iteratively marking the multiples of each prime number starting from 2.

code.js
1function sieveOfEratosthenes(n) { 2 // All numbers except 0 and 1 are prime 3 const sieve = Array(n + 1).fill(true) 4 sieve[0] = sieve[1] = false 5 6 // Check all numbers up to n 7 for (let i = 2 ; i * i <= n ; i++) { 8 // If i is prime, mark all its multiples as non-prime 9 if (sieve[i]) { 10 for (let j = i * i ; j <= n ; j += i) { 11 sieve[j] = false 12 } 13 } 14 } 15 16 // Return the index of all numbers that are prime 17 return sieve.map((isPrime, index) => isPrime ? index : null).filter(Boolean) 18}

In practice, this is the most efficient method for finding many prime numbers up to around .

Prime Factorization

Prime factorization is the process of expressing a number as a product of prime numbers. For example, the prime factorization of 12 is 2 * 2 * 3.

code.js
1function primeFactorization(n) { 2 const factors = [] 3 for (let i = 2; i * i <= n; i++) { 4 while (n % i === 0) { 5 factors.push(i) 6 n /= i 7 } 8 } 9 if (n > 1) factors.push(n) 10 return factors 11}
  1. Trial Division: This is the simplest method, where you divide the number by all integers up to its square root. It is straightforward but inefficient for large numbers. The time complexity is .

  2. Sieve of Eratosthenes: While primarily used for finding prime numbers, it can be adapted for factorization by precomputing primes up to a certain limit and using them to divide the number.

  3. Pollard's Rho Algorithm: This is a probabilistic algorithm that is particularly effective for numbers with small factors. It has an expected time complexity of .

  4. Fermat's Factorization Method: This method is based on the representation of an odd integer as a difference of two squares. It works well when the number has factors close to its square root. The time complexity is approximately .

  5. Quadratic Sieve: This is one of the fastest factorization algorithms for numbers with up to 100 digits. It uses a combination of sieving and linear algebra. The time complexity is sub-exponential, approximately .

  6. Elliptic Curve Factorization: This algorithm uses properties of elliptic curves to find factors and is effective for numbers with small to medium-sized factors. The time complexity is similar to Pollard's Rho, , but can be more efficient in practice.

  7. General Number Field Sieve (GNFS): This is the most efficient classical algorithm for factoring very large numbers, typically those with more than 100 digits. It is a complex algorithm with a time complexity of .

Each of these algorithms has its own strengths and is chosen based on the size and nature of the number to be factored. For practical applications, a combination of these methods is often used to achieve optimal performance.