Ошибка в типах (JS)

Решаю задачу на Codewars, ссылка: https://www.codewars.com/kata/670031c78cc02fa6c28ba28a/train/javascript

Получаю ошибку:

"return BigInt(sum); RangeError: The number Infinity cannot be converted to a BigInt because it"

Как преобразовать infinity к BigInt, или нужно пропускать Infinity?

Когда пропускаю Infinity получаю другие результаты — как исправить?

Работает только с маленькими n:

Корректное прохождение тестов

С тысячными n уже ошибка:

Ошибка на тесте

Код:

function channellingPrimes(n) {
    const res = 0;
    const bits = [];
    let sum = 0;
  
    function isPrime( num ) {
        if( num <= 1 )
            return false;
        
        for( i = 2; i * i <= num; i ++) { 
            if( num % i == 0 ) return false;
        }
        return true;
    }
  
    for(let i = 1; i <= n; i++) {
        if(isPrime(i)) {
            bits.push(1);
        } else {
            bits.push(0);
        }
    }
  
    for(let i = 0; i < bits.length; i++) {
        if(bits[i] === 1) {
            sum += Math.pow(2, i);
        }
    }
    
    return BigInt(sum);
}

console.log(channellingPrimes(4800));

Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Ошибка возникает потому что Math.pow(2, i) для больших i не помещается в вещественное число порождая Infintity:

for (let i = 1020; ; i++) {
    const p = Math.pow(2, i);
    console.log(i, p)
    BigInt(p);
}

Минимальная правка простая: суммирование в хвосте функции перевести целиком на BitInt:

    ...
    let sum = 0n;
    for(let i = 0; i < bits.length; i++) {
        if(bits[i] === 1) {
            sum += 2n ** BigInt(i);
        }
    }
    return BigInt(sum);

Но, как правильно сказали в комментариях, лучше собрать из битов двоичный литерал вида '0b...' и сконструировать из него BigInt в один вызов. К этому я добавлю, что индивидуальная проверка простоты не нужна. Решето Эратосфена работает быстрее и требует меньше кода. И построить из него результат проще:

function channellingPrimes(n) {
    const sieve = new Uint8Array(n + 1);
    sieve.fill(1, 2);

    for (let i = 2; ; ++i) {
        if (sieve[i]) {
            const i2 = i * i;
            if (i2 > n) {
                break;
            }
            for (let j = i2; j <= n; j += i) {
                sieve[j] = 0;
            }
        }
    }
    const bits = sieve.subarray(1);
    bits.reverse();
    return BigInt(`0b${bits.join('')}`);
}
→ Ссылка