Skip to content

Instantly share code, notes, and snippets.

@hugmanrique
Last active January 30, 2021 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hugmanrique/2e4966a6edc55bb2f47770d5d5f36e91 to your computer and use it in GitHub Desktop.
Save hugmanrique/2e4966a6edc55bb2f47770d5d5f36e91 to your computer and use it in GitHub Desktop.
Checks if a number is perfect
// Every perfect number is represented as p one bits followed by (p - 1) zero bits,
// where p is a Mersenne prime.
// Let x be the largest `MAX_BITS`-bit perfect number. Then ceil(log2(x)) = p + (p - 1).
const MAX_BITS = 32; // Bitwise operators operate on 32-bit integers
const MAX_ONES = Math.floor((MAX_BITS + 1) / 2); // upper bound on p
// Precomputed list of all prime m <= p s.t. 2^m - 1 is prime.
// TODO Compute automatically.
const MERSENNE_EXPS = new Set([2, 3, 5, 7, 13]);
function isPerfect(n) {
// Iterate through initial (p - 1) zeros.
let p;
for (p = 1; !(n & 1) && p < MAX_ONES; p++) {
n >>= 1;
}
// If the given value is perfect, n is now (2^p - 1).
if (n !== ((1 << p) - 1)) {
return false;
}
return MERSENNE_EXPS.has(p);
}
// https://oeis.org/A000396
[6, 28, 496, 8128, 33550336].forEach(n => {
if (!isPerfect(n)) {
console.log(`isPerfect returned false for perfect n=${n}`);
}
});
[
// Some pernicious numbers (https://oeis.org/A052294)
3, 5, 7, 9, 10, 11, 12, 26, 2096128,
// Other non-perfect numbers
0, 1, 2, 4, 8, 13, 27, 130816
].forEach(n => {
if (isPerfect(n)) {
console.log(`isPerfect returned true for non-perfect n=${n}`);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment