Как стать автором
Обновить

Комментарии 47

const sub = (a, b) => a + (Number.MAX_SAFE_INTEGER ^ b) + 1
Интересно. Но опять же работает не везде. sub(1.1, 3.1) == -1.9
Не вижу ошибки. В точность, заданную операндами, укладывается.
З.Ы. Это я с точки зрения математики, не знаток спецификации JS. если ей противоречит тогда да, ошибка.
С точки зрения математики 1.1 — 3.1 — это строго -2 же.
НЛО прилетело и опубликовало эту надпись здесь
Первая мысль, особенно после строчки 31 декабря 1969 года, это Integer Overflow. В js получить не получилось, в php работает:
php > echo PHP_INT_MIN + PHP_INT_MAX;
-1
В JS, по сути, нет интов. Так что не судьба(
> 4294967295|0
-1
> new Int8Array([255])[0];
-1
А, точно. Типизированные массивы. Вот это я упустил, да.
Это все может пригодится на практике? В чем суть этого задания, отучить использовать простые и очевидные решения?
Это задание учит следующему:

1. Знать свой инструмент.
2. Иметь воображение.
3. Если однажды возникнет необходимость написать жуткий, но необходимый костыль, иметь интеллектуальную готовность это сделать.

Разумеется, чтобы третий пункт был плюсом, а не минусом, нужно также научиться не писать костыли, пока это действительно не окажется необходимо.
А как же KISS? А потом удивляемся откуда берутся простыни текста в методах.
Всё следует упрощать до тех пор, пока это возможно, но не более того (с)

Естественный пример, зачем нужно такое вычитание, я придумать, конечно, не могу — задача осознанно искусственная. Можно пофантазировать о том, что JS необходимо запустить в некоторой багнутой среде, где интерпретатор крашится на символе "-". Но вообще случается так, что реальные задачи требуют хаков. И если ты всю жизнь программировал строго по учебнику, столкновение с первой такой задачей похоже по ощущениям на столкновение лица с асфальтом.

Пожалуйста, только не давайте таких задач студентам с их неокрепшей психикой и несформировавшимся понятиями о том, что допустимо в промышленной разработке, а что нет. Опытным разработчикам, которые понимают границы применимости, — пожалуйста, но не студентам. Иначе подобный код всплывёт потом на работе просто потому что "а почему бы нет, работает же, стильно-модно-молодёжно" и будет очень больно.

Ну, если так рассуждать, студентам и сортировку пузырьком нельзя проходить. а то потом напишут её вместо Array#sort и просадят производительность к чертям.
Вы не поверите! Но я видел код в продакшене, где вместо встроенных сортировок, писали свои:)
Ну так и я как-то раз писал. Array#sort не гарантирует стабильность сортировки, хотя бы по этой причине иногда может понадобиться свой велосипед.

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

Я думаю, студенты затруднятся не меньше моего)
Вообще, введение понятия должно сопровождаться как примерами того, что в этом понятие входит, так и примерами того, что в него не входит. Так что для объяснения того, что такое хороший, добротный код, надо иногда и грязные хаки демонстрировать.

Если это приподнести как пример того, как делать не стоит, то конечно, нет проблем :) Просто нужно чтобы это явно было сказано с самого начала, чтобы понимание формировалось у студентов) Чтобы люди четко и ясно понимали, что так делать нельзя в общем случае) Поверьте, это может быть далеко не очевидно для многих)

Да, согласен, тут мой косяк. В прошлых статьях серии я чаще упомнал, что тот, кто будет так делать в продакшоне, попадёт в ад)
Обфускация :)
Придет потом студент домой и будет изобретать бесконечное количество вариантов, как можно решить задачу, не используя «инструменты из коробки», вместо изучения чего-либо полезного. Потом такой студент выйдет работать и будет придумывать искуственные ситуации, когда надо придумывать подобные решения. Программирование изначально точная наука, в таком ключе, лучше в театральный идти — там воображение разовьют как надо и на практике пригодится.
Да ни разу программирование не точная наука. Теория алгоритмов — да. Программирование — нет. Разница как между физикой и инженерией.
Не хочу с вами спорить, пусть будет так, но здравый смысл должен присутствовать всегда, тем более при обучении кого-либо. А то так можно книку написать с главами вида: складываем два числа не используя "+", умножаем не используя "*", и так далее.
Организуем обмен данными, не используя глобальное состояние. Программируем, не изменяя объекты. Пишем функции, результат выполнения которых зависит только от их входных данных =) Передёргиваю, конечно, но всё же…
У меня была книга о реализации математической библиотеки типа стандартной JS, плюс неограниченной точности в среде, где максимум что есть сложение, вычитание и битовые операции 16-бит чисел. Ассемблер i8080 если что.
Написать функцию sub(a, b), которая будет находить разность чисел a и b. Однако в тексте функции не должно быть символа "-".

function sub(a, b){
    return sub_internal(a, b);
}

function sub_internal(a, b){
    return a - b;
}
Я ждал этого коммента) да, точная формулировка будет «в тексте функции, модуля, содержащего эту функцию, а также всех модулей, используемых этой функцией». Но она уж больно громоздкая.
let sub = (a, b) => ~(~a + b)

Как-то так, для целых должно работать.
1^0xfffffffe старый добрый xor но нужно посмотреть, разрядность системы х64 или х32
Можно считать инты 32-битными, независимо от системы. Но на самом деле там не инты)
Можно считать инты 32-битными, независимо от системы.
Хотя я вот написал и задумался, правда ли это.
Я не увидел в стандарте, какой диапазон у числовых значений. Вполне возможно, что старые версии JS сверху были ограничены 32 бита, а новые или те что только планируют будут ограничены 64 битами ну или другим количеством.

В стандарте явно сказано, что битовые операции преобразуют аргументы в int32.

Спасибо, проглядел.
Как вариант можно циклом вычислять разницу, способ конечно примитивный, но работать будет.
let sub = function(a,b){
    let result = 0;
    let start = b;
    let end = a;
    if (a >= b) {
        for (let i = start; i<end; i++) {
             result++;
	}
    }
    else {
        for (let i = end; i<start; i++) {
	    result--;
	}
    }
    return result;
}
result--;
упс)
Только сейчас понял в чем косяк решения) Вместо того, чтобы использовать минус использовал сразу два) Пойду поаплодирую себе за решение)
Вариант попроще:

int sub(int a, int b)
{
    if (a == b) return 0;
    if (a > b) return sub(b, a);
    var i = 0;
    while (a < b)
    {
        i++;
        a++;
    }
    return i;
}


Вариант посложнее:
int sub(int a, int b)
{
  if (a == b) return 0;
  if (b == a + 1) return 1;
  if (a > b) return sub(b, a);
  int sum = 0;
  if (a%2 == 1 ^ b%2 == 1) sum = 1;
  sum += 2 * sub(a, (a +b) / 2);
  return sum;
}


Правда, оба варианта возвращают разность по модулю… Пойду подумаю еще.
int sub(int a, int b)
{
    if (a == b) return 0;
    if (b == a + 1) return 1;
    if (a > b) return (int)Math.Log10(0.1d) * sub(b, a);
    int sum = 0;
    if (a % 2 == 1 ^ b % 2 == 1) sum = 1;
    sum += 2 * sub(a, (a + b) / 2);
    return sum;
}


Варианты с распарсиванием строки в число с указанием номера символа "-" я счел чересчур читерскими )
А впрочем, можно куда проще, и так, чтобы работало не только для целых:

return a + Math.Log10(0.1) * b;


Но так даже скучно )

В порядке бреда :)


String(Number.MIN_SAFE_INTEGER)[0] + 1 | 0 // -1

Ещё чуточку идиотии :)


getComputedStyle(document.body)[0].replace(/\w+/g, '') + 1 | 0 // -1

Очень хочется выцепить "-" как-нибудь через try-catch и поиск символа в тексте ошибки, но что-то никак не могу подобрать подходящую ошибку. Попробовал с регулярками повоевать — тоже пока ничего хитрого не придумал :)

Точно. Собирался написать что-нибудь с DOMом, но забыл.

Спасибо. Напомнило измерение высоты здания с помощью барометра.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории