Простая задачка на Си++
2020-08-02 04:29Сложить два целых числа, вернуть целое. Породить исключение в случае арифметического переполнения.
Удивительно, сколько народу обламывается на этой задачке.int add(int a, int b);

no subject
Date: 2020-08-02 11:49 (UTC)https://en.cppreference.com/w/cpp/language/try_catch
— выше сил аппликантов?
no subject
Date: 2020-08-02 12:19 (UTC)no subject
Date: 2020-08-02 17:51 (UTC)no subject
Date: 2020-08-02 13:00 (UTC)Короткий гугл-поиск дает ответ (только gcc конечно):
no subject
Date: 2020-08-02 13:08 (UTC)А когда вставляют в код ответ не от той задачи, совсем весело.
no subject
Date: 2020-08-02 13:13 (UTC)Первая истина для разработчика -- не умножай сущностей,
то есть не выдумывай заново, то что уже придумано до тебя.
Если человек не нашел builtin'a в гугле, то он уже не квалифицирован для разработки.
И знает ли он о том что signed integer overflow это UB или не знает это уже совершенно неважно.
(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2020-08-04 00:12 (UTC)no subject
Date: 2020-08-02 13:13 (UTC)no subject
Date: 2020-08-02 15:08 (UTC)Довольно логично, и не так уж неэффективно.
no subject
Date: 2020-08-02 16:17 (UTC)Короче, настоящий программист ломанётся в дебри и обязательно запутается, потому что не успеет продумать все ньюансы.
(no subject)
From:no subject
Date: 2020-08-02 18:59 (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2020-08-02 18:37 (UTC)Т.е. там более длинных целочисленных типов просто нет.
(no subject)
From:(no subject)
From:no subject
Date: 2020-08-02 13:29 (UTC)Для беззнаковых типичный паттерн проверки на переполнение — это сложить и проверить, что результат сложения не меньше одного из операндов (любого). А для знаковых — не знаю, ветвиться по знаковости операндов нужно, наверное, на все четыре случая. А в ветках - сводить всё к беззнаковым и применять тот же приёмчик. Это в предположении, что просто перейти к типам большей размерности нельзя, например, такая платформа, что sizeof(int) == sizeof(intmax_t).
no subject
Date: 2020-08-02 13:45 (UTC)Internally, the overflow flag is usually generated by an exclusive or of the internal carry into and out of the sign bit.
Мило, но вряд-ли аппликант на работу додумается до этого на собеседовании, если не знает заранее.
Carry out of the sign bit можно вычислить, как я уже говорил, после кастинга обоих операндов к unsigned int, их сложения, и сравнения суммы с любым из них, например первым. Если сумма беззнаковых меньше первого беззнакового — значит бит Carry out равен 1, иначе 0.
Carry in можно вычислить, просто применив AND-маску ((unsigned int)(INT_MAX)) к обоим операндам в беззнаковой форме перед сложением. Нужный нам бит "Carry in of the sign bit" будет в старшем бите результата после сложения.
А далее просто XOR этих carry in и carry out, как учит Википедия. :)
Интересно, найдётся ли компилятор, который преобразует все эти извращения обратно в инструкцию чтения флага OF.
no subject
Date: 2020-08-02 15:09 (UTC)Достаточно проверить равенство знаков, и пробовать сложить абсолютные величины.
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2020-08-02 14:22 (UTC)int add(int a, int b) { int sum = a + b; if (a > 0 && b > 0 && sum < -1) { throw std::overflow_error("result too positive"); } else if (a < 0 && b < 0 && sum > -1) { throw std::overflow_error("result too negative"); } return sum; }no subject
Date: 2020-08-02 18:38 (UTC)(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2020-08-02 18:07 (UTC)int add(int a, int b) { int sum = a + b; if (~(a ^ b) & (a ^ sum) & INT_MIN) throw overflow_error("arithmetic overflow"); return sum; }no subject
Date: 2020-08-02 18:22 (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2020-08-02 21:08 (UTC)Но вообще задачка проверяет не столько знание Си, сколько умение искать информацию :-)
no subject
Date: 2020-08-02 22:31 (UTC)no subject
Date: 2020-08-03 06:10 (UTC)(no subject)
From:no subject
Date: 2020-08-03 08:43 (UTC)Кто все эти безумные люди, которые рассуждают про unsigned, какие-то там детали реализации каких-то там конкретных версий языков программирования, про битовые операции, 2's complement представление? Какая нахер разница? Машина может быть хоть троичная симметричная, и не иметь понятия об "unsigned".Пятикласснику должно быть понятно, что достаточно знать только MAX и MIN для данного типа операндов, и делается это так: нарочно не на языке программирования, а на естественном языке.
1. Если хотя бы одно из чисел равно нулю или числа с разным знаком, то складываем без опаски.
2. Если оба числа положительные, то вычтем из MAX одно из них. Если разность меньше другого числа, то бросаем исключение.
3. Если оба числа отрицательные, то вычтем из MIN одно из них. Если разность больше другого числа, то бросаем исключение.
4. Складываем числа, возвращаем результат.
По-хорошему, спрашивать надо про
template< typename T > int add(const T & a, const T & b);и вопрос тогда будет про type traits (который синтаксис я так и не запомнил).no subject
Date: 2020-08-03 19:14 (UTC)Не, тепмплейты на собеседовании это уже издевательство. :) В такую контору я бы и сам не пошёл.
no subject
Date: 2020-08-03 23:30 (UTC)А уж если мы говорим про язык Си, то мы обычно говорим об этом не для красоты, а для того чтоб писать эффективный и быстрый код. Потому что если вам не нужен такой код, то зачем вам Си? Берите Питон или JS какой-нибудь в самом деле. Ну а если вам нужен эффективный и быстрый код, то вам никогда-никогда не следует использовать вышеуказанный алгоритм для пятиклассников. Потому что он медленный, плохо-читается,
в нем легко сделать ошибку, которую потом будет трудно найти.
Но спасибо за такой вариант. Я еще раз убедился, что даже в мире программистов на Си есть миры, которые не просто слегка отличаются, а не соприкасаются друг с другом вообще. Какая уж там политика может быть, когда люди не просто разные бывают, а многие прямо-таки абсолютно чужды друг другу.
(no subject)
From: