Подтвердить что ты не робот

Зачем вам нужно переполнение целых чисел?

В этом вопросе тема заключается в том, как заставить VS проверить арифметическое переполнение в С# и выбросить исключение: Переполнение С# не работает? Как включить проверку переполнения?

В одном из комментариев было сказано что-то странное и получилось много, надеюсь, вы можете мне помочь:

Вы также можете использовать ключевое слово checked для переноса оператора или набора инструкций, чтобы они явно проверялись на арифметическое переполнение. Устанавливать свойство всего проекта немного рискованно, потому что часто переполнение является довольно разумным ожиданием.

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

Зачем вам когда-либо ожидать переполнение и почему бы вам не предотвратить его, если у вас есть такая возможность? (путем установки соответствующей опции компилятора)

4b9b3361

Ответ 1

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

Мы проверили арифметику, включенную по всему проекту для Noda Time - я предпочел бы исключить исключение, чем возвращать неверные данные. Я подозреваю, что это довольно редко для переполнения, чтобы быть желательным... Я соглашусь, я обычно оставляю по умолчанию неконтролируемую арифметику, просто потому, что она по умолчанию. Там, конечно, и скорость, конечно...

Ответ 2

Я всегда думал о переполнении undefined и должно быть предотвращается, когда это возможно.

Вы также можете смутить разницу между переполнением буфера (overrun) и числовым переполнением.

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

Однако числовое переполнение четко определено. Например, если у вас есть 8-битный регистр, он может хранить только 2 ^ 8 значений (от 0 до 255, если без знака). Поэтому, если вы добавите 100 + 200, вы не получите 300, а 300 по модулю 256, что составляет 44 года. Рассказ немного сложнее с использованием подписанных типов; битовый шаблон увеличивается аналогичным образом, но они интерпретируются как два дополнения, поэтому добавление двух положительных чисел может дать отрицательное число.

Ответ 3

При выполнении вычислений с постоянно увеличивающимися счетчиками. Классическим примером является Environment.TickCount:

int start = Environment.TickCount;
DoSomething();
int end = Environment.TickCount;
int executionTime = end - start;

Если это было проверено, программа имеет шанс бомбить 27 дней после загрузки Windows. Когда TickCount тикает за пределы int.MaxValue во время выполнения DoSomething. PerformanceCounter - еще один пример.

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

Ответ 4

Уголки

Целые числа, которые переполняют, являются изящными инструментами для измерения углов. У вас 0 == 0 градусов, 0xFFFFFFFF == 359.999.... градусов. Это очень удобно, потому что в качестве 32-битных целых чисел вы можете добавлять/вычитать углы (350 градусов плюс 20 градусов заканчиваются переполнением, обертывая назад до 10 градусов). Также вы можете решить использовать 32-битное целое число как подписанное (от -180 до 180 градусов) и без знака (от 0 до 360). 0xFFFFFFF равно -179.999..., что равно 359.999..., что равнозначно. Очень элегантно.

Ответ 5

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

По умолчанию проверенная арифметика не включена по умолчанию, так это то, что проверенная арифметика медленнее, чем непроверенная арифметика. Если производительность не является проблемой для вас, вероятно, имеет смысл включить проверенную арифметику, поскольку возникновение переполнения обычно является ошибкой.

Ответ 6

При генерации HashCodes, скажем, из строки символов.

Ответ 7

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

Кроме того, большинство процессоров предназначены для переполнения, но устанавливают бит переноса в процессе, что упрощает реализацию добавления в более длинных, чем естественные, словах. Для реализации проверочных операций в этом контексте будет добавлен код для создания исключения, если флаг переноса установлен. Не огромное навязывание, а то, что писатели-компиляторы, вероятно, не хотели навязывать людям без выбора.

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

Ответ 8

Вы можете рассчитывать на то, что измеряется для дельт. Некоторое сетевое оборудование поддерживает небольшие размеры счетчиков, и вы можете опросить значение, скажем, переданные байты. Если значение становится слишком большим, оно просто переполняется до нуля. Он по-прежнему дает вам что-то полезное, если вы часто его измеряете (байты/минута, байт/час), а так как счетчики обычно очищаются, когда соединение падает, неважно, что они не совсем точны.

Как сказал Джастин, переполнение буфера - это другой чайник рыбы. Здесь вы пишете в конце массива в память, которую вы не должны делать. При числовом переполнении используется тот же объем памяти. В переполнении буфера используется память, которую вы не выделили. Переполнение буфера автоматически предотвращается на некоторых языках.

Ответ 9

Существует один классический рассказ о программисте, который воспользовался переполнением в дизайне программы:

История Мела

Ответ 10

Это не столько связано с тем, как работают регистры, сколько ограничениями памяти в переменных, которые хранят данные. (Вы можете переполнять переменную в памяти, не переполняя никаких регистров.)

Но чтобы ответить на ваш вопрос, рассмотрите простейший тип контрольной суммы. Это просто сумма всех проверяемых данных. Если контрольная сумма переполнена, это нормально, а часть, которая не переполнена, по-прежнему имеет смысл.

Другие причины могут включать в себя то, что вы просто хотите, чтобы ваша программа продолжала работать, даже если несущественная переменная могла переполниться.

Ответ 11

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

Ответ 12

Переполнение целых чисел происходит следующим образом.

У вас есть 8-битное целое число 1111 1111, теперь добавьте 1 к нему. 0000 0000, ведущий 1 получает усечение, так как он будет в 9-й позиции.

Теперь скажите, что у вас есть целое число со знаком, ведущий бит означает отрицательный. Итак, теперь у вас есть 0111 1111. Добавьте 1 к нему, и у вас есть 1000 0000, что составляет -128. В этом случае добавление 1 к 127 заставило его переключиться на отрицательный.

Я очень уверен, что переполнения ведут себя хорошо определенным образом, но я не уверен о нижних уровнях.

Ответ 13

Вся целая арифметика (как правило, добавляет вычитания и умножает как минимум) точна. Это просто интерпретация полученных бит, которые вам нужно соблюдать. В системе с двумя дополнениями вы получаете правильный результат по модулю 2 для количества бит. Единственное различие между подписанным и unsigned заключается в том, что для подписанных номеров наиболее значимый бит рассматривается как знаковый бит. Его до программиста определить, что подходит. Очевидно, что для некоторых вычислений вы хотите узнать о переполнении и предпринять соответствующие действия, если они обнаружены. Лично я никогда не нуждался в обнаружении переполнения. Я использую линейный конгруэнтный генератор случайных чисел, который полагается на него, то есть 64 * 64-битное беззнаковое целочисленное умножение, я забочусь только о самых младших 64 битах, я получаю операцию по модулю бесплатно из-за усечения.