isPerfectNumber function
Checks if a number is a perfect number. A perfect number is a positive integer that is equal to the sum of its positive divisors, excluding the number itself.
Example:
print(isPerfectNumber(6)); // Output: true
print(isPerfectNumber(28)); // Output: true
print(isPerfectNumber(12)); // Output: false
print(isPerfectNumber(137438691328)); // Output: true
print(isPerfectNumber(137438691329)); // Output: false
print(isPerfectNumber('2305843008139952128')); // Output: true
Implementation
bool isPerfectNumber(dynamic n) {
BigInt parseInput(dynamic n) {
if (n is BigInt) return n;
if (n is int) return BigInt.from(n);
return BigInt.parse(n.toString());
}
({BigInt powerOfTwo, BigInt remaining}) factorOutPowersOfTwo(BigInt n) {
BigInt power = BigInt.zero;
while (n.isEven) {
n = n ~/ BigInt.two;
power += BigInt.one;
}
return (powerOfTwo: power, remaining: n);
}
bool checkEvenPerfectStructure(BigInt n) {
try {
final factorization = factorOutPowersOfTwo(n);
final possibleP = factorization.remaining + BigInt.one;
if (!possibleP.isPowerOfTwo) return false;
final p = possibleP.bitLength - 1;
final expectedPower = p - 1;
// Verify the structure: 2^(p-1) * (2^p - 1)
return factorization.powerOfTwo == BigInt.from(expectedPower) &&
isMersennePrime(p);
} catch (_) {
return false;
}
}
bool checkOddPerfectCandidate(BigInt n) {
// Known constraints for hypothetical odd perfect numbers:
// 1. Must be > 10^1500
// 2. Must have at least 101 prime factors
// 3. Must be of form N = q^k m^2 where q ≡ k ≡ 1 (mod 4)
if (n.toString().length < 1501) return false;
// Optimized divisor sum with early exit
BigInt sum = BigInt.one;
final sqrtN = n.sqrt();
var i = BigInt.two;
while (i <= sqrtN && sum <= n) {
if (n % i == BigInt.zero) {
final pair = n ~/ i;
sum += i == pair ? i : i + pair;
}
i += i.isEven
? BigInt.one
: BigInt.two; // Skip even divisors for odd numbers
}
return sum == n;
}
final number = parseInput(n);
if (number <= BigInt.one) return false;
// First check for even perfect number structure
if (number.isEven && checkEvenPerfectStructure(number)) {
return true;
}
// Then check for odd number properties (unknown but possible)
return checkOddPerfectCandidate(number);
}