Рассчитать произведение чисел с плавающей запятой с арифметикой с фиксированной запятой
У меня есть две работы:
- Мне нужно сохранить два значения датчика в памяти (используя FPU)
- а затем рассчитать произведение этих двух значений без FPU.
Мои датчики:
- Датчик 1 выдает значения от 0 до 40 с разрешением 0,2
- Датчик 2 выдает значения от -10 до 10 с разрешением 0,1
Чтобы хранить данные эффективным способом, я преобразовал значения в целые числа, используя смещение и коэффициент масштабирования
uint8 uint_value = (floating_value - offset) / resolution;
Пример данных: датчик 1:
Real World Value 0.0 -> uint_value = 0
Real World Value 20.2 -> uint_value = 101
Датчик 2:
Real World Value -10.0 -> uint_value = 0
Real World Value 0.5 -> uint_value = 105
Сейчас у меня проблемы со вторым заданием. Мне нужно рассчитать произведение этих двух значений без использования арифметики с плавающей запятой.
Как мне это сделать? Я взглянул на числа с фиксированной запятой, которые дают возможность умножения на целочисленное умножение и сдвиг. Но я не могу понять, как преобразовать мои масштабированные значения в числа с фиксированной запятой.
2 ответа
Проблема, с которой вы сталкиваетесь, заключается в том, что 0.2 и 0.1 не могут быть представлены точно как двоичные дроби. Вы умножили одно значение на 5, а другое на 10. В какой-то момент вам нужно разделить их произведение на 50, что невозможно с помощью простого сдвига. Ваши вычисления не будут точными, независимо от того, используете ли вы операции с плавающей запятой или с фиксированной запятой. Вы должны спросить себя, сколько точности вам требуется в результате.
Чтобы использовать арифметику с фиксированной точкой, умножьте значение каждого датчика на степень 2, скажем, 256. Используйте 16-битную переменную со знаком и не вычитайте смещение. Результат этого умножения будет иметь верхние 8 битов, представляющих целую часть показаний датчика, и нижние 8 битов, представляющих неточную дробную часть показаний датчика.
Умножьте эти два 16-битных значения, чтобы получить 32-битный результат со знаком. Нижние шестнадцать бит представляют дробную часть продукта. Теперь вы можете округлить или усечь эти дробные биты до желаемого уровня точности. Но вы не можете сказать, что ваша точность будет 0,02, потому что это не рациональное двоичное значение. Ваша точность должна быть в форме 1/2^F, где F - количество битов дроби, которые вы сохраните в окончательном ответе.
Выполните умножение целых чисел, а затем сдвиньте десятичную сумму на сумму ваших шкал.