Моя программа часто требует выполнения следующих расчетов:
Дано:
- N - это 32-разрядное целое число
- D - это 32-разрядное целое число
- abs (N) & lt; = abs (D)
- D! = 0
- X - это 32-разрядное целое число любого значения
Найти:
- X * N/D как округленное целое число, то есть X, масштабированное до N/D (т.е. 10 * 2/3 = 7)
Очевидно, я мог бы просто использовать r=x*n/d
напрямую, но я часто получаю переполнение от x*n
. Если я вместо этого сделаю r=x*(n/d)
, то получу только 0 или x из-за целочисленного деления, отбрасывающего дробный компонент. И затем есть r=x*(float(n)/d)
, но я не могу использовать поплавки в этом случае.
Точность была бы велика, но она не так критична, как скорость и была бы детерминированной функцией (всегда возвращала одно и то же значение при одинаковых входных данных).
N и D в настоящее время подписаны, но я могу обойтись без них, если это поможет.
Универсальная функция, которая работает с любым значением X (и N и D, если N & lt; = D), является идеальной, поскольку эта операция используется различными способами, но у меня также есть конкретный случай, когда значение X представляет собой известная постоянная сила 2 (2048, если быть точным), и просто ускорить этот конкретный вызов было бы большой помощью.
В настоящее время я выполняю это, используя 64-битное умножение и деление, чтобы избежать переполнения (по сути, int multByProperFraction(int x, int n, int d) { return (__int64)x * n / d; }
, но с некоторыми утверждениями и дополнительными битами для округления вместо усечения).
К сожалению, мой профилировщик сообщает, что 64-битная функция деления занимает слишком много ЦП (это 32-битное приложение). Я пытался уменьшить частоту выполнения этих вычислений, но у меня не хватает способов их обойти, поэтому я пытаюсь найти более быстрый метод, если это возможно. В конкретном случае, когда X - это постоянная 2048, я использую битовое смещение вместо умножения, но это мало помогает.