I thought I’d post a few code snippets in C# that have to do with basic number theory, since I use them in my programs from time to time. These snippets are by no means optimized, and the use of C# pretty much precludes their use in high-performance applications. Still, for relatively small arguments, these routines run surprisingly fast.
Prime numbers
To generate a list of prime numbers, we use the familiar Sieve of Eratosthenes. We can write one routine to generate the sieve:
bool[] GetPrimeSieve(long upTo)
{
long sieveSize = upTo + 1;
bool[] sieve = new bool[sieveSize];
Array.Clear(sieve, 0, (int)sieveSize);
sieve[0] = true;
sieve[1] = true;
long p, max = (long)Math.Sqrt(sieveSize) + 1;
for (long i = 2; i <= max; i++)
{
if (sieve[i]) continue;
p = i + i;
while (p < sieveSize) { sieve[p] = true; p += i; }
}
return sieve;
}
The above function returns an array of booleans (the size of the given parameter), each of which is false if the array index is a prime number, or true if it's not a prime number. To get an actual list of prime numbers, we can use a function such as this:
long[] GetPrimesUpTo(long upTo)
{
if (upTo < 2) return null;
bool[] sieve = GetPrimeSieve(upTo);
long[] primes = new long[upTo + 1];
long index = 0;
for (long i = 2; i <= upTo; i++) if (!sieve[i]) primes[index++] = i;
Array.Resize(ref primes, (int)index);
return primes;
}
The above function returns an actual list of primes less than or equal to the specified high limit. This means that we can easily compute the prime-counting function $$\pi(x)$$ for any integer x by counting the number of elements in the array returned by the function. We can write a similar function to generate a list of composites:
long[] GetCompositesUpTo(long upTo)
{
if (upTo < 2) return null;
bool[] sieve = GetPrimeSieve(upTo);
long[] composites = new long[upTo + 1];
long index = 0;
for (long i = 2; i <= upTo; i++)
if (sieve[i]) composites[index++] = i;
Array.Resize(ref composites, (int)index);
return composites;
}
As for determining if a single certain number is prime (without having to generate a giant sieve), we can simply use a function that attempts to factor the number. If the number happens to be divisible by an integer greater than 1 and less than or equal to its square root, then the number is not prime:
bool IsPrime(long n)
{
long max = (long)Math.Sqrt(n);
for (long i = 2; i <= max; i++)
if (n % i == 0)
return false;
return true;
}
Greatest Common Divisor and Totient
To obtain the greatest common divisor (GCD) of two numbers, we use the usual Euclidean algorithm:
long gcd(long a, long b)
{
long temp;
while (b != 0)
{
temp = b;
b = a % b;
a = temp;
}
return a;
}
There is a slightly different binary algorithm for computing the GCD which is theoretically more efficient, but in practice (at least in C#) it's actually slightly less efficient than the algorithm above:
ulong gcdb(ulong a, ulong b)
{
int shift;
if (a == 0 || b == 0) return a | b;
for (shift = 0; ((a | b) & 1) == 0; ++shift) { a >>= 1; b >>= 1; }
while ((a & 1) == 0) a >>= 1;
do {
while ((b & 1) == 0) b >>= 1;
if (a < b) {
b -= a;
} else {
ulong temp = a - b;
a = b;
b = temp;
}
b >>= 1;
} while (b != 0);
return a << shift;
}
With the GCD readily available, determining whether two numbers are coprime is just a matter of telling whether or not their GCD is equal to 1. Also, calculating the LCM (least common multiple) of two numbers becomes trivial:
long lcm(long a, long b)
{
long ret = 0, temp = gcd(a, b);
if (temp != 0)
{
if (b > a) ret = (b / temp) * a;
else ret = (a / temp) * b;
}
return ret;
}
Also using the GCD algorithm, it becomes easy to calculate Euler's totient function for a certain number, since the totient function is simply the number of integers less than or equal to n that are coprime to n:
long eulerTotient(long n)
{
long sum = 0;
for (long i = 1; i <= n; i++)
if (gcd(i, n) == 1) sum++;
return sum;
}
The above is a really naive algorithm. A much more efficient algorithm (one that is usually given in textbooks) is as follows:
int eulerTotient(int n)
{
primes = GetPrimesUpTo(n+1); //this can be precalculated beforehand
int numPrimes = primes.Length;
int totient = n;
int currentNum = n, temp, p, prevP = 0;
for (int i = 0; i < numPrimes; i++)
{
p = (int)primes[i];
if (p > currentNum) break;
temp = currentNum / p;
if (temp * p == currentNum)
{
currentNum = temp;
i--;
if (prevP != p) { prevP = p; totient -= (totient / p); }
}
}
return totient;
}
I beg your pardon?! Of all the websites in the world, banking sites should be the most secure by definition. And yet, here we are with Huntington’s website telling us to limit our password to 16 characters, and not use any special characters!
Again, they tell us not to use special characters, and to limit the length of our password. Even though the length limitation here is 32 characters, my question is why is there a length limitation? And why can’t special characters be used?