Показать сообщение отдельно
  #17 (permalink)  
Старый 25.05.2020, 23:47
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от laimas
А кто-то вел речь о десятичных?
Раз использовался Array, а не конкретный типизированный массив для целых чисел; а также тип Number, то странно предполагать, что речь идёт не о десятичных числах. Совершенно спокойно можно написать дробное число и оно будет неверно обработано. Может для тебя ОК писать код, который делает неожиданные вещи и продолжает выполняться, но я предпочёл бы использовать правильный тип или выкидывать исключение при нарушении требовании (диапазон целых чисел и проверка на целочисленность)

Использование правильного типа оберегает от проблем...
function doubleEveryEven (a) {
    return a.map(n => n * (2n - (n & 1n)));
}
console.log(doubleEveryEven([11n, 0n, 9n, 3n, 10n, 4n]));
В этом примере вы можете использовать целые числа и всегда получать правильное вычисление.

Если же хотите использовать тип Number и работать именно с целыми числами и использовать оператор &, то следует провести проверки.

Хотя оператор & работает с 32-битными числами, он подходит для задачи, поскольку нас интересует только последний бит.

function doubleEveryEven (a) {
    return a.map(n => {
        if(!Number.isSafeInteger(n))
            throw new RangeError(`The provided number ${n} is not a safe integer to operate with.`);

        if((n & 1) == 0) {
            const doubleN = 2 * n;

            if(!Number.isSafeInteger(doubleN))
                throw new RangeError(`The calculated number ${doubleN} is not a safe integer to operate with.`);

            return doubleN;
        } else {
            return n;
        }
    });
}
console.log(doubleEveryEven([11, 0, 9, 3, 10, 4]));


Почему удвоенное число типа Number тоже проверяется на безопасность? Поскольку безопасное число, умноженное на 2, может оказаться не безопасным...
alert(8456834563856384 * 2 === 16913669127712767);
А на самом деле так...
alert(8456834563856384n * 2n === 16913669127712767n);


Что же касается умножения при помощи побитового сдвига, то нужно учитывать, что работает с 32-битными числами от -(2 ** 31) до 2 ** 31 - 1.

function doubleEveryEven (a) {
    return a.map(n => {
        if(Number.isSafeInteger(n) && ((n > 2 ** 31 - 1) || (n < -(2 ** 31))))
            throw new RangeError(`The provided number ${n} is not a safe 32-bit integer to operate with.`);

        if((n & 1) == 0) {
            if((n > 2 ** 30 - 1) || (n < -(2 ** 30)))
                throw new RangeError(`A double of number has got to be a safe 32-bit integer to operate with.`);

            return n << 1;
        } else {
            return n;
        }
    });
}
console.log(doubleEveryEven([11, 0, 9, 3, 10, 4]));


Сообщение от Vlasenko Fedor
laimas, абсолютно правильно написал для целых чисел
Не упомянуты проверки, соответственно не для всех целых чисел правильные результаты.

Сообщение от Vlasenko Fedor
поясни почему интересное и правильное с твоей точки зрения
Если именно для типа Number и кол-во значащих цифр не имеет значения, но тут оказалось всё хуже — пишем тип Number, думаем о BigInt.
Ответить с цитированием