Эти параметры не представляют собой целые числа. Они представляют действительные числа в формате с фиксированной точкой с 15 битами справа от точки счисления. Например, 1,0 представлен 1 < < 15 = 0x8000, 0,5 - 0x4000, -0,5 - 0xC000 (или 0xFFFFC000 в 32 бит).
Добавление чисел с фиксированной точкой является простым, поскольку вы можете просто добавить их целочисленное представление. Но если вы хотите размножаться, вам сначала нужно умножить их на целые числа, но тогда у вас в два раза больше битов справа от точки счисления, поэтому вам придется отбросить избыток, сдвинув его. Например, если вы хотите размножить 0.5 самостоятельно в 32-битном формате, вы умножаете 0x00004000 (1 < < 14) сами по себе, чтобы получить 0x10000000 (1 < 28), затем сдвиньте вправо на 15 бит, чтобы получить 0x00002000 (1 < < 13). Чтобы получить лучшую точность, когда вы отбрасываете самые низкие 15 бит, вы хотите округлить до ближайшего номера, а не округлить вниз. Вы можете сделать это, добавив 0x4000 = 1 < < 14. Тогда, если отброшенные 15 бит меньше 0x4000, он округляется, а если это 0x4000 или более, он округляется.
(0x3FFF + 0x4000) >> 15 = 0x7FFF >> 15 = 0
(0x4000 + 0x4000) >> 15 = 0x8000 >> 15 = 1
Подводя итог, можно сделать умножение следующим образом:
return (o32 * o16 + 0x4000) >> 15;
Но есть проблема. В C++ результат умножения имеет тот же тип, что и его операнды. Таким образом, o16
рекламируется до того же размера, что и o32
, а затем умножается на получение 32-битного результата. Но это отбрасывает верхние биты, потому что для получения точного представления для продукта требуется 16 + 32 = 48 бит. Один из способов сделать это - отбросить операнды до 64 бит, а затем размножаться, но это может быть медленнее и не поддерживается на всех машинах. Таким образом, вместо этого он разбивает o32
на две 16-битные части, затем выполняет два умножения в 32 битах и объединяет результаты.
Похоже, что это было написано на платформе, в которой нет встроенных 32-битных множителей. – Mysticial
Это должно быть какое-то специализированное оборудование, верно? Будет ли работа с прямым умножением работать на обычных ПК? – misha
@ user1708860: попробуйте googling имя функции. Это не домашнее задание. – misha