Отказ от ответственности: я знаю, целые числа без знака являются примитивными числовыми типами, но они не переполняются технически, я использую термин «переполнение» для всех примитивных числовых типов в целом здесь.
в C или C ++, в соответствии со стандартом или конкретной реализацией, существуют примитивные числовые типы, в которых задана арифметическая операция, даже если эта операция может переполниться, я могу сохранить результат + плюс часть, которая переполняется?
Даже если это звучит странно, моя идея состоит в том, что регистры на современных процессорах обычно намного больше, чем 32-битные float
или 64 бит uint64_t
Таким образом, существует возможность фактически контролировать переполнение и хранить его где-нибудь.
Нет, регистры не «обычно намного больше, чем 64-битные uint64_t
».
Существует флаг переполнения, и для ограниченного числа операций (сложение и вычитание) достаточно объединения этого единственного дополнительного бита с результатом, чтобы охватить весь диапазон результатов.
Но в целом вам необходимо преобразовать данные в более крупный тип (возможно, реализованный в программном обеспечении) для обработки результатов, которые выходят за пределы типа вашего ввода.
Любые операции, которые делают подобные вещи (например, некоторые 32-разрядные процессоры имели инструкцию умножения 32×32 => 32, 32 или 32), будут предоставлены вашим компилятором как встроенные функции или через встроенную сборку.
смотри, я нашел 64-битную версию, названную Multiply128 а также соответствие __mul128
доступно в Visual C ++
Смотрите @Ben Voigt о больших регистрах.
На самом деле может быть только бит переполнения, который мог помочь тебе.
Другой подход, не прибегая к более широким целым числам, заключается в тестировании переполнения самостоятельно:
unsigned a,b,sum;
sum = a + b;
if (sum < a) {
OverflowDetected(); // mathematical result is `sum` + UINT_MAX + 1
}
Подобный подход для int
,
Следующее, вероятно, может быть упрощено — просто не имейте под рукой.
int
переполнение, см Более простой метод для обнаружения переполнения int
int a,b,sum;
sum = a + b;
// out-of-range only possible when the signs are the same.
if ((a < 0) == (b < 0)) {
if (a < 0) {
if (sum > b) UnderflowDetected();
}
else {
if (sum < b) OverflowDetected();
}
Для типа с плавающей точкой вы можете фактически контролировать переполнение на платформе x86. С этими функциями «_control87, _controlfp, __control87_2», Вы можете получить и установить управляющее слово с плавающей точкой. По умолчанию библиотеки времени выполнения маскируют все исключения с плавающей точкой; вы можете разоблачить их в своем коде, поэтому при переполнении вы получите исключение. Однако в коде, который мы пишем сегодня, все предполагают, что исключения с плавающей запятой замаскированы, поэтому, если вы снимите их, вы столкнетесь с некоторой проблемой.
Вы можете использовать эти функции чтобы получить статусное слово.
Для типов с плавающей запятой результаты хорошо определены аппаратным обеспечением, и вы не сможете получить много контроля, не работая с C / C ++.
Для целочисленных типов меньше чем int
они будут увеличены до int
любой арифметической операцией. Вероятно, вы сможете обнаружить переполнение, прежде чем вернуть результат в меньший тип.
Для сложения и вычитания вы можете обнаружить переполнение, сравнивая результат с входными данными. Добавление двух натуральных чисел всегда будет давать результат, больший, чем любой из входных данных, если только не было переполнения.