Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как умножить в массиве только нечётные числа? (https://javascript.ru/forum/misc/80330-kak-umnozhit-v-massive-tolko-nechjotnye-chisla.html)

laimas 25.05.2020 01:03

Цитата:

Сообщение от Malleys
Не будет, например, 4.3 будет считаться чётным числом

А кто-то вел речь о десятичных? Даже детишки знают, что для целых чисел деление можно заменить логическим сдвигом, четность проверять по младшему разряду, по естественным причинам. Десятичное представление иное.

Vlasenko Fedor 25.05.2020 10:34

Цитата:

Сообщение от Malleys
Error, просто, интересно и правильное решение!

поясни почему интересное и правильное с твоей точки зрения
const doubleEveryEven = arr => arr.map(n => 0 === n % 2 ? n + n : n);

здесь нет лишнего умножения
Error,
приветсвую, если аватарка таже
laimas,
абсолютно правильно написал для целых чисел

Error 25.05.2020 12:56

Vlasenko Fedor,
приветствую Вас! Да, это я. Что касается моего решения, то мне захотелось избежать применения любых условных операторов. Хотя это, конечно, не должно быть целью.

Понятие чётности вводится обычно именно для целых чисел (для рациональных нет смысла рассматривать вопросы делимости). Поэтому предлагаю считать, что все элементы массива — целые числа. Значит, любое решение, применимое к целым числам, можно считать правильным.

voraa 25.05.2020 15:52

Цитата:

Сообщение от laimas
Даже детишки знают, что для целых чисел деление можно заменить логическим сдвигом,

Поосторожнее надо быть детишкам.
console.log(2**30<<1)

laimas 25.05.2020 15:57

Цитата:

Сообщение от voraa
Поосторожнее надо быть детишкам

:stop: Но, но, это также как и с десятичными, не всегда будет гут, но с другой стороны мы же иногда и округляем, а значит допускаем. А деление, это сдвиг вправо, а не влево ;)

Vlasenko Fedor 25.05.2020 16:30

Цитата:

Сообщение от voraa
Поосторожнее надо быть детишкам.
console.log(2**30<<1)

a<<b
умножение числа a на 2 в степени b
console.log(2**30&1)

Malleys 25.05.2020 23:47

Цитата:

Сообщение от 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.

laimas 26.05.2020 03:22

Malleys,
и зачем это научный труд, неужели бы все отвечающие не вели посты свои в ключе необходимом, если бы условием было для всех и вся?

Цитата:

Сообщение от Malleys
Совершенно спокойно можно написать дробное число

Однако же не написано.

Malleys 26.05.2020 04:24

Цитата:

Сообщение от laimas
и зачем это

Ты сам написал, что твои детки знают про целочисленные сдвиги, а разве они не знают про то, что с этим могут возникнуть проблемы когда будут неподходящие целые числа?

Твой метод хорош, просто нужно было уточнить, что он правильно работает только с типом BigInt, а с типом Number требуются дополнительные проверки!

laimas 26.05.2020 12:50

Цитата:

Сообщение от Malleys
Твой метод хорош, просто нужно было уточнить

Это не мой метод, а если руководствоваться постулатом "Раз использовался Array, а не конкретный типизированный массив для целых чисел; а также тип Number, то странно предполагать, что речь идёт не о десятичных числах.", то надо смотреть ширше, ибо массив может содержать и другое. Почему тогда не добавить еще и о проверке типа перед нами, например, в стрингах он или нет, и можно ли его вообще умножать.

Все увидели в том, что представлено, только то, что увидели для этого и даны решения различные, и они все правильные. А если предполагать, что там может быть что-то, ну так все об этом уже высказались - будет, значит нужно брать подходящее.

Это же касается и о логическом сдвиге, такие операции быстрые ибо это операция над одним орперандом в аккумуляторе, она выгоднее. Но никто же и говорил, что такая операция способна на все, никто же не использует операторы/функции, которые не дают нужного результата, стоит ли об этом говорить.


Часовой пояс GMT +3, время: 21:11.