Grizzly 0 Posted February 28, 2014 (edited) · Report post В наследство досталось много кода, написанного уволившимся программистом. Ищу ошибки, разбираюсь. Специфика программы в том, что код был изначально написан под TMS с фиксированной точкой, затем был перенесем на ARM7, где часть операций стала производиться с вещественными числами. Есть множество приведений типов. Нашел баг. UINT64 p1, p2; ... REAL64 Power = (REAL64)(p1-p2); Когда разность получалась отрицательной, результат был неверный. Корректно ли делать приведение типов так? Power = (REAL64)p1-(REAL64)p2; Или нужно сначала разность привести к SINT64, а затем уже к REAL64? Edited February 28, 2014 by Grizzzly Quote Ответить с цитированием Share this post Link to post Share on other sites
smalcom 0 Posted March 1, 2014 · Report post >> Power = (REAL64)p1-(REAL64)p2; так верно Quote Ответить с цитированием Share this post Link to post Share on other sites
DpInRock 0 Posted March 1, 2014 · Report post Изначально неверно использовать UINT для арифметических операций со знаком. Экономия одного бита при 64 разрядах вряд ли оправдана. Quote Ответить с цитированием Share this post Link to post Share on other sites
Grizzly 0 Posted March 1, 2014 · Report post >> Power = (REAL64)p1-(REAL64)p2; так верно Спасибо! У меня выходило, что этот вариант не всегда прокатывал. В программе p1, p2 могут принимать значения в диапазоне от 50000 до нескольких десятков миллионов. Тут такое приведение типов срабатывало. При тестировании взял такие значения: p1 = 800000000000000000, p2 = 800000000000000001. Тогда работает вариант UINT64 t = p[0]-p[1]; Power = (REAL64)((SINT64)t); , а в первом случае ошибка. Теперь понял, что так получалось из-за того, что в примере было больше 16 значащих десятичных цифр. Изначально неверно использовать UINT для арифметических операций со знаком. Экономия одного бита при 64 разрядах вряд ли оправдана. Согласен. Что досталось, с тем и пришлось работать... Quote Ответить с цитированием Share this post Link to post Share on other sites
maksimp 0 Posted March 1, 2014 · Report post При тестировании взял такие значения: p1 = 800000000000000000, p2 = 800000000000000001. Тогда работает вариант Чтобы не терять точность в подобных случаях можно например так: Power = (p1>=p2) ? ((REAL64)(p1-p2)) : (-(REAL64)(p2-p1)); Фактически нужно 65-битную промежуточную переменную, и результат (p1>=p2) как раз хранит дополнительный бит. Quote Ответить с цитированием Share this post Link to post Share on other sites
Grizzly 0 Posted March 2, 2014 · Report post Фактически нужно 65-битную промежуточную переменную, и результат (p1>=p2) как раз хранит дополнительный бит. Спасибо. Quote Ответить с цитированием Share this post Link to post Share on other sites