Ошибка в типах (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 шт):
Ошибка возникает потому что 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('')}`);
}

