Всем привет.
На Codeforces Round 184 (Div. 2) моё решение взломали из-за переполнения во время умножения. В связи с эти вопрос. Если есть две переменные типа int64, то как проверить, происходит ли переполнение при вычислении a*b?
№ | Пользователь | Рейтинг |
---|---|---|
1 | tourist | 4009 |
2 | jiangly | 3823 |
3 | Benq | 3738 |
4 | Radewoosh | 3633 |
5 | jqdai0815 | 3620 |
6 | orzdevinwang | 3529 |
7 | ecnerwala | 3446 |
8 | Um_nik | 3396 |
9 | ksun48 | 3390 |
10 | gamegame | 3386 |
Страны | Города | Организации | Всё → |
№ | Пользователь | Вклад |
---|---|---|
1 | cry | 166 |
2 | maomao90 | 163 |
2 | Um_nik | 163 |
4 | atcoder_official | 161 |
5 | adamant | 159 |
6 | -is-this-fft- | 158 |
7 | awoo | 157 |
8 | TheScrasse | 154 |
9 | nor | 153 |
9 | Dominater069 | 153 |
Всем привет.
На Codeforces Round 184 (Div. 2) моё решение взломали из-за переполнения во время умножения. В связи с эти вопрос. Если есть две переменные типа int64, то как проверить, происходит ли переполнение при вычислении a*b?
Название |
---|
Например, так:
Можно, например, так:
c = a * b;
if (c / a != b) {
// переполнение
}
Или так: log(a) + log(b) > log(INF)
Приведённые выше примеры либо могут быть неточными (
double
), либо со знаковыми типами вызывают неопределённое поведение (c = a * b
).Если числа неотрицательные, то проверить можно примерно так:
Однако полезность такой проверки мне представляется сомнительной. Допустим, что логика решения этой проверки не требует и нам нужно вывести как раз это
a * b
. Теперь мы вставляем проверку и на каком-то тесте обнаруживаем потенциальное переполнение. И что теперь делать, раз ответ всё равно не вычислен? С таким же успехом можно и вообще не проверять. Вывод: надо просто писать решение так, чтобы возможность переполнения никогда не возникала.Зато не так редко возникает ситуация, когда в коде
if(a*b<=n)...
значения переменных a, b и n порядка 1018. И тогда действительно вместо умножения втупую надо писать через деление.