За все годы программирования встраиваемых систем мне вообще никогда не приходилось работать с отрицательными числами. Это сумасшествие, но они просто не часто встречаются в моей работе.
В настоящее время я имею дело с показаниями датчика, которые могут быть положительными или отрицательными, и их необходимо масштабировать на 0,006, сохраняя знак. Чтобы избежать ненужных вычислений с плавающей запятой во время выполнения, у меня есть алгоритм, который преобразует это в числитель и знаменатель (3/500). Все работает, как и ожидалось, с положительными числами, но вот что происходит с отрицательными:
Raw data: -103
Multiplied by 3: -309
Divided by 500: 36893488147419102
Я понял, откуда берется это число, и у меня есть обходной путь, но я предпочитаю верить, что математика есть математика.
Вот тот же расчет в шестнадцатеричном формате:
Raw data: 0xFFFFFFFFFFFFFF99
Multiplied by 3: 0xFFFFFFFFFFFFFECB
Divided by 500: 0x0083126E978D4FDE
В калькуляторе (SpeedCrunch):
0xFFFFFFFFFFFFFECB/500 = 0x83126E978D4FDE.9D2F1A9FBE76C8B44
Этот исходный 36893488147419102
является неотъемлемой частью 0x83126E978D4FDE
результата SpeedCrunch.
Я не хочу сохранять знак, делать положительное деление, а затем снова добавлять знак каждый раз, когда я делаю деление с отрицательными числами. Что тут происходит?
Среда — CortexM3 micro, GCC4.9.3 с использованием С++ 11. Вычисления выполняются на int64_t
, а числитель/знаменатель uint64_t
.
Изменить: Вот фрагмент кода в ответ на комментарий Майкла ниже:
int64_t data = -103;
uint64_t resolutionNumerator = 3;
uint64_t resolutionDenominator = 500;
data *= resolutionNumerator;
data /= resolutionDenominator;