Самое быстрое решение, наименее гибкое: используйте собственные типы данных, которые будут выполнять обертывание в аппаратном обеспечении.
Абсолютно быстрый метод для обёртывания целых чисел должен был бы гарантировать, что ваши данные масштабируются до int8 / int16 / int32 или любого другого собственного типа данных. Тогда, когда вам понадобятся данные для переноса, родной тип данных будет сделан аппаратно! Очень безболезненно и на несколько порядков быстрее , чем любая реализованная здесь реализация переноса программного обеспечения.
В качестве примера тематического исследования:
Я считаю, что это очень полезно, когда мне нужна быстрая реализация sin / cos, реализованная с использованием справочной таблицы для реализации sin / cos. По сути, вы производите масштабирование данных таким образом, чтобы INT16_MAX был pi, а INT16_MIN - -pi. Тогда вы готовы идти.
В качестве дополнительного примечания, масштабирование ваших данных добавит некоторую предварительную конечную стоимость вычислений, которая обычно выглядит примерно так:
int fixedPoint = (int)( floatingPoint * SCALING_FACTOR + 0.5 )
Не стесняйтесь обменивать int на что-то еще, что вы хотите, например int8_t / int16_t / int32_t.
Следующее самое быстрое решение, более гибкое: вместо этого мод работает медленно, если возможно, попробуйте использовать битовые маски!
Большинство решений, которые я просмотрел, являются функционально правильными ... но они зависят от работы мода.
Работа мода очень медленная, потому что она по существу делает аппаратное деление . Непрофессионалы объясняют, почему мод и деление медленные, приравнивают операцию деления к некоторому псевдокоду for(quotient = 0;inputNum> 0;inputNum -= divisor) { quotient++; }
(по умолчанию , частное и делитель ). Как видите, аппаратное деление может быть быстрым , если оно является низким числом относительно делителя ... но деление может также быть ужасно медленным, если оно намного больше делителя * 1035. *.
Если вы можете масштабировать данные до степени, равной двум, тогда вы можете использовать битовую маску, которая будет выполняться за один цикл (на 99% всех платформ), и ваше повышение скорости составит приблизительно один порядок величины ( как минимум в 2 или 3 раза быстрее) .
C-код для реализации упаковки:
#define BIT_MASK (0xFFFF)
int wrappedAddition(int a, int b) {
return ( a + b ) & BIT_MASK;
}
int wrappedSubtraction(int a, int b) {
return ( a - b ) & BIT_MASK;
}
Не стесняйтесь сделать #define чем-то, что выполняется во время выполнения. И не стесняйтесь отрегулировать битовую маску так, чтобы она была такой, какая вам нужна. Например, 0xFFFFFFFF или степень двойки, которую вы решаете реализовать.
p.s. Я настоятельно рекомендую прочитать об обработке с фиксированной запятой при работе с условиями обтекания / переполнения. Я предлагаю прочитать:
Арифметика с фиксированной точкой: введение Рэнди Йейтса 23 августа 2007 г.