ПРИМЕЧАНИЕ. Это теоретический вопрос. Я доволен производительностью моего кода как такового. Мне просто интересно, есть ли альтернатива.
Есть ли уловка для целочисленного деления постоянного значения, которое само является целочисленной степенью двойки, на целочисленное значение переменной, без необходимости использовать операцию фактического деления?
// The fixed value of the numerator
#define SIGNAL_PULSE_COUNT 0x4000UL
// The division that could use a neat trick.
uint32_t signalToReferenceRatio(uint32_t referenceCount)
{
// Promote the numerator to a 64 bit value, shift it left by 32 so
// the result has an adequate number of bits of precision, and divide
// by the numerator.
return (uint32_t)((((uint64_t)SIGNAL_PULSE_COUNT) << 32) / referenceCount);
}
Я нашел несколько (много) ссылок на трюки с делением на константу, как целочисленную, так и с плавающей запятой. Например, на вопрос Какой самый быстрый способ разделить целое число на 3? есть несколько хороших ответов, включая ссылки на другие академические и общественные материалы.
Учитывая, что числитель является постоянным и представляет собой целую степень двойки, есть ли хитрый трюк, который можно было бы использовать вместо фактического 64-битного деления; какая-то побитовая операция (сдвиги, AND, XOR и тому подобное) или подобное?
Я не хочу потери точности (сверх возможной полубита из-за округления целых чисел) большей, чем при фактическом делении, поскольку точность прибора зависит от точности этого измерения.
«Пусть решает компилятор» - не ответ, потому что я хочу знать, есть ли уловка.
Дополнительная контекстная информация
Я разрабатываю драйвер на микроконтроллере с 16-битными данными и 24-битным командным словом. Драйвер творит чудеса с периферийными модулями, чтобы получить счетчик импульсов опорной частоты для фиксированного числа импульсов частоты сигнала. Требуемый результат - это отношение сигнальных импульсов к опорному импульсу, выраженное в виде 32-битного значения без знака. Арифметика функции определяется производителем устройства, для которого я разрабатываю драйвер, и результат обрабатывается дальше, чтобы получить реальное значение с плавающей запятой, но это выходит за рамки этого вопроса.
Микроконтроллер, который я использую, имеет цифровой сигнальный процессор, который имеет ряд операций деления, которые я мог бы использовать, и я не боюсь делать это в случае необходимости. При таком подходе придется преодолеть некоторые незначительные проблемы, помимо сборки инструкций по сборке, чтобы заставить его работать, например, использование DSP для выполнения функции PID в ISR драйвера BLDC, но я не могу справиться с этим.
No
. - person Klas Lindbäck   schedule 28.01.2016referenceCount
? Полный 32-битный диапазон? - person chux - Reinstate Monica   schedule 28.01.20161/referenceCount
и составлению дроби, масштабированнойSIGNAL_PULSE_COUNT
, OP может допускать небольшую ошибку, прямойpower_of_2/x
слишком медленный. Предположим,SIGNAL_PULSE_COUNT == 0
не беспокоит. Дайте этому посту немного времени. - person chux - Reinstate Monica   schedule 28.01.2016referenceCount
никогда не будет больше 24 бит. «Идеальный» диапазон находится между (приблизительно) 0x120000 и 0xB40000. Фактический диапазон зависит от физических факторов окружающей среды, таких как давление и температура, но это приведет к тому, что пределы диапазона изменятся не более чем на несколько сотен. И да, «трюк» по сути сводится к нахождению обратной величины, выраженной целым числом, с некоторым заранее определенным масштабированием. - person Evil Dog Pie   schedule 28.01.2016SIGNAL_PULSE_COUNT
, равным 1:10. 2) Воспользуйтесь предыдущими расчетами, поскольку, как я предполагаю,SIGNAL_PULSE_COUNT
не меняется слишком быстро. 3) Отсутствие ответов не означает отсутствие ответов, Терпение молодого кузнечика. - person chux - Reinstate Monica   schedule 28.01.2016__builtin_
функции для обеспечения доступа к инструкциям DSP из C.) - person Evil Dog Pie   schedule 29.01.2016