isPerfectNumber function

bool isPerfectNumber(
  1. dynamic n
)

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);
}