isxxxx
Version:
Lightweight library for checking number properties and mathematical classifications
569 lines (449 loc) • 13.9 kB
JavaScript
function isEven(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return num % 2 === 0;
}
function isOdd(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return num % 2 !== 0;
}
function isPositive(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return num > 0;
}
function isNegative(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return num < 0;
}
function isZero(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return num === 0;
}
function isPrime(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 1) return false;
if (num <= 3) return true;
if (num % 2 === 0 || num % 3 === 0) return false;
let i = 5;
while (i * i <= num) {
if (num % i === 0 || num % (i + 2) === 0) return false;
i += 6;
}
return true;
}
function isMultipleOf(num, multiple) {
if (typeof num !== 'number' || typeof multiple !== 'number') throw new TypeError('Expected numbers');
if (multiple === 0) throw new Error('Cannot check for multiples of zero');
return num % multiple === 0;
}
function isInRange(num, min, max) {
if (typeof num !== 'number' || typeof min !== 'number' || typeof max !== 'number') throw new TypeError('Expected numbers');
return num >= min && num <= max;
}
function isPerfectSquare(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const sqrt = Math.sqrt(num);
return Math.floor(sqrt) === sqrt;
}
function isInteger(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return Number.isInteger(num);
}
function isPowerOfTwo(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return num > 0 && (num & (num - 1)) === 0;
}
function isPowerOf(num, base) {
if (typeof num !== 'number' || typeof base !== 'number') throw new TypeError('Expected numbers');
if (base <= 0 || num <= 0) return false;
if (base === 1) return num === 1;
let power = 1;
while (power < num) {
power *= base;
}
return power === num;
}
function isPerfect(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 1) return false;
let sum = 1;
for (let i = 2; i * i <= num; i++) {
if (num % i === 0) {
sum += i;
if (i !== num / i) sum += num / i;
}
}
return sum === num;
}
function isFibonacci(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
return isPerfectSquare(5 * num * num + 4) || isPerfectSquare(5 * num * num - 4);
}
function isFactorial(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 1) return false;
if (num === 1) return true;
let factorial = 1, i = 2;
while (factorial < num) {
factorial *= i++;
}
return factorial === num;
}
function isPalindrome(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const str = num.toString();
const len = str.length;
for (let i = 0; i < len / 2; i++) {
if (str[i] !== str[len - 1 - i]) return false;
}
return true;
}
function isSafeInteger(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
return Number.isSafeInteger(num);
}
function isTriangular(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const check = 8 * num + 1;
const sqrt = Math.sqrt(check);
return Math.floor(sqrt) === sqrt;
}
function isHexagonal(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const check = 8 * num + 1;
const sqrt = Math.sqrt(check);
return Math.floor(sqrt) === sqrt && sqrt % 2 === 1;
}
function isPentagonal(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const check = 24 * num + 1;
const sqrt = Math.sqrt(check);
return sqrt === Math.floor(sqrt) && (sqrt + 1) % 6 === 0;
}
function isArmstrong(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const digits = num.toString().split('').map(Number);
const power = digits.length;
const sum = digits.reduce((acc, digit) => acc + Math.pow(digit, power), 0);
return sum === num;
}
function isHappy(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
const seen = new Set();
while (num !== 1 && !seen.has(num)) {
seen.add(num);
num = num.toString().split('').reduce((sum, digit) => sum + Math.pow(Number(digit), 2), 0);
}
return num === 1;
}
function isHarshad(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
const digitSum = num.toString().split('').reduce((sum, digit) => sum + Number(digit), 0);
return num % digitSum === 0;
}
function isSmith(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 1) return false;
if (isPrime(num)) return false;
const digitSum = num.toString().split('').reduce((sum, digit) => sum + Number(digit), 0);
let n = num;
let primeFactorSum = 0;
for (let i = 2; i * i <= n; i++) {
while (n % i === 0) {
primeFactorSum += i.toString().split('').reduce((sum, digit) => sum + Number(digit), 0);
n /= i;
}
}
if (n > 1) {
primeFactorSum += n.toString().split('').reduce((sum, digit) => sum + Number(digit), 0);
}
return digitSum === primeFactorSum;
}
function isPowerful(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
if (num === 1) return true;
let n = num;
for (let i = 2; i * i <= n; i++) {
if (n % i === 0) {
if (n % (i * i) !== 0) return false;
while (n % i === 0) n /= i;
}
}
return n > 1 ? num % (n * n) === 0 : true;
}
function isAbundant(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
let sum = 0;
for (let i = 1; i <= num / 2; i++) {
if (num % i === 0) sum += i;
}
return sum > num;
}
function isDeficient(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
let sum = 0;
for (let i = 1; i <= num / 2; i++) {
if (num % i === 0) sum += i;
}
return sum < num;
}
function isSelfNumber(num, limit = 10000) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
if (limit > 100000) limit = 100000;
const upperBound = Math.min(num, limit);
for (let i = 1; i <= upperBound; i++) {
const digitSum = i.toString().split('').reduce((sum, digit) => sum + Number(digit), 0);
if (i + digitSum === num) return false;
}
return true;
}
function isAutomorphic(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
return (num * num).toString().endsWith(num.toString());
}
function isNarcissistic(num) {
return isArmstrong(num);
}
function isCarmichael(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 1) return false;
if (isPrime(num)) return false;
function modPow(base, exponent, modulus) {
if (modulus === 1) return 0;
let result = 1;
base = base % modulus;
while (exponent > 0) {
if (exponent % 2 === 1) result = (result * base) % modulus;
exponent = Math.floor(exponent / 2);
base = (base * base) % modulus;
}
return result;
}
function gcd(a, b) {
while (b !== 0) {
const temp = b;
b = a % b;
a = temp;
}
return a;
}
for (let a = 2; a < num; a++) {
if (gcd(a, num) === 1 && modPow(a, num - 1, num) !== 1) return false;
}
return true;
}
function isKaprekar(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 1) return false;
const square = num * num;
const squareStr = square.toString();
for (let i = 1; i < squareStr.length; i++) {
const part1 = parseInt(squareStr.substring(0, i), 10);
const part2 = parseInt(squareStr.substring(i), 10);
if (part2 > 0 && part1 + part2 === num) return true;
}
return false;
}
function isAlternating(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const digits = num.toString().split('').map(Number);
if (digits.length <= 1) return true;
for (let i = 1; i < digits.length; i++) {
if ((digits[i] % 2 === 0) === (digits[i-1] % 2 === 0)) return false;
}
return true;
}
function isApocalyptic(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
return (BigInt(2) ** BigInt(num)).toString().includes('666');
}
function isLucas(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num === 2 || num === 1) return true;
if (num < 0) return false;
let a = 2, b = 1, c;
while (b < num) {
c = a + b;
a = b;
b = c;
if (b === num) return true;
}
return false;
}
function isCatalan(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
const smallCatalans = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440];
if (num <= 2674440) return smallCatalans.includes(num);
let catalan = 1, n = 1;
while (catalan < num) {
catalan = (catalan * (4 * n - 2)) / (n + 1);
n++;
if (catalan === num) return true;
}
return false;
}
function isBell(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
const smallBells = [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, 678570, 4213597];
return smallBells.includes(num);
}
function isMersennePrime(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
return !((num + 1) & num) && isPrime(num);
}
function isFermat(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
if ([3, 5, 17, 257, 65537].includes(num)) return true;
if (num < 65537) return false;
for (let n = 5; n <= 20; n++) {
try {
const fermat = BigInt(2) ** BigInt(2 ** n) + BigInt(1);
if (fermat.toString() === num.toString()) return true;
if (fermat > BigInt(Number.MAX_SAFE_INTEGER)) break;
} catch (e) {
break;
}
}
return false;
}
function isCullen(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
for (let n = 1; n <= 100; n++) {
const cullen = n * Math.pow(2, n) + 1;
if (cullen === num) return true;
if (cullen > num) return false;
}
return false;
}
function isWoodall(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
for (let n = 1; n <= 100; n++) {
const woodall = n * Math.pow(2, n) - 1;
if (woodall === num) return true;
if (woodall > num) return false;
}
return false;
}
function isPronic(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const sqrt = Math.sqrt(num);
const floor = Math.floor(sqrt);
return floor * (floor + 1) === num;
}
function isRepunit(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
return /^1+$/.test(num.toString());
}
function isSquareFree(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
for (let i = 2; i * i <= num; i++) {
if (num % (i * i) === 0) return false;
}
return true;
}
function isUndulant(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num < 0) return false;
const digits = num.toString().split('').map(Number);
if (digits.length <= 2) return false;
for (let i = 1; i < digits.length - 1; i++) {
if (!((digits[i-1] < digits[i] && digits[i] > digits[i+1]) ||
(digits[i-1] > digits[i] && digits[i] < digits[i+1]))) {
return false;
}
}
return true;
}
function isPractical(num) {
if (typeof num !== 'number') throw new TypeError('Expected a number');
if (num <= 0) return false;
if (num === 1) return true;
const divisors = [1];
for (let i = 2; i <= Math.sqrt(num); i++) {
if (num % i === 0) {
divisors.push(i);
if (i !== num / i) divisors.push(num / i);
}
}
divisors.sort((a, b) => a - b);
for (let i = 1; i < Math.pow(2, divisors.length); i++) {
let sum = 0;
for (let j = 0; j < divisors.length; j++) {
if ((i >> j) & 1) sum += divisors[j];
}
if (sum >= 1 && sum < num && !divisors.includes(sum)) return false;
}
return true;
}
module.exports = {
isEven,
isOdd,
isPositive,
isNegative,
isZero,
isPrime,
isMultipleOf,
isInRange,
isPerfectSquare,
isInteger,
isPowerOfTwo,
isPowerOf,
isPerfect,
isFibonacci,
isFactorial,
isPalindrome,
isSafeInteger,
isTriangular,
isHexagonal,
isPentagonal,
isArmstrong,
isHappy,
isHarshad,
isSmith,
isPowerful,
isAbundant,
isDeficient,
isSelfNumber,
isAutomorphic,
isNarcissistic,
isCarmichael,
isKaprekar,
isAlternating,
isApocalyptic,
isLucas,
isCatalan,
isBell,
isMersennePrime,
isFermat,
isCullen,
isWoodall,
isPronic,
isRepunit,
isSquareFree,
isUndulant,
isPractical
};