Вопрос

У меня есть код, написанный на C и предназначенный для 16-битного микроконтроллера.По сути, код выполняет множество арифметических операций с плавающей запятой.

Арифметика работает нормально, пока результат не будет положительным, но в случае вычитания, если ожидаемый результат отрицательный, я получаю ноль.

result = 0.005 - 0.001;      Is correctly computed as 0.004
result = 0.001 - 0.005;      Is always zero.

Почему такое поведение для float?

Это было полезно?

Решение

Интересный.Это вполне может быть ошибка в программном обеспечении с плавающей запятой.Встроенные системы часто включают плавающую запятую в качестве опции, чтобы уменьшить размер кода.

Я не уверен, что проблема здесь, поскольку ваше первое утверждение работает.

Что происходит с:

result = 0.005 - 0.001;
result = -result;

result = 0.002 - 0.001;
result = 0.002 - 0.002;
result = 0.002 - 0.003;

result = 0.001 - 0.002;
result = 0.001 - 0.003;
result = 0.001 - 0.004;

Идея здесь состоит в том, чтобы собрать полезную информацию о том, что может быть причиной этого, что является обычным делом в криминалистике.Результаты этих расчетов, вероятно, помогут определить реальную проблему.

По вашим результатам в комментариях:

result = 0.005 - 0.001;  // 0.004
result = -result;        // 0.000
result = 0.002 - 0.001;  // 0.001
result = 0.002 - 0.002;  // 0.000
result = 0.002 - 0.003;  // 0.000
result = 0.001 - 0.002;  // 0.000
result = 0.001 - 0.003;  // 0.000
result = 0.001 - 0.004;  // 0.000

Похоже, у вашей библиотеки с плавающей запятой есть серьезный недостаток.Еще два вопроса:

  • Как вы распечатываете результаты (покажите нам действительный код)?
  • Какой микроконтроллер и среду разработки вы используете?

Возможно, возникла проблема со способом печати или ограничениями вашей среды.

Аджит, я думаю, тебе действительно придется дать нам код, который поможет тебе.Не обязательно ваш реальный код (ваше беспокойство по поводу выпуска реального кода понятно), просто тот, который демонстрирует проблему.

Судя по некоторым вашим комментариям, а именно:

Адриан, тип данных для «результата» — это число с плавающей запятой, то есть 32-битное представление (одиночное).У меня есть МОЖЕТ в качестве системного интерфейса, поэтому я умножаю результат на 1000, чтобы отправить его по шине CAN.Если это отрицательное число, например -0,003, то я ожидаю FF FD в сообщении CAN.У меня нет отладчика.

Не уверен, что полностью понимаю, но попробую.

У вас есть 32-битное число с плавающей запятой, например -0,003, и вы умножаете его на 1000 и поместите это в целое число (0xFFFD — это 16-битное представление числа -3 с дополнением до двух).Итак, что произойдет, если вы запустите что-то вроде следующего кода:

int main(void) {
    float w = -0.003;
    int x = (int)(w * 1000);
    int y = -3;
    int z = -32768;
    // Show us you code here for printing x, y and z.
    return 0;
}

Причина, по которой я хочу, чтобы вы проверили целое число, заключается в том, что оно может иметь ничего вообще иметь дело с поплавками.Возможно, значение с плавающей запятой совершенно правильное, но есть некоторая проблема со способом его печати (метод CAN).

Если «CAN» — это своего рода последовательный интерфейс, возможно, существует ограничение на количество байтов, которые вам разрешено отправлять через него.Я могу представить себе сценарий, в котором старшие байты используются в качестве маркеров пакета, так что FF может фактически завершить сообщение преждевременно.Вот почему я также хочу, чтобы вы проверили -32768 (0x8000).

Трудно поверить в это СТМикроэлектроника создаст такую ​​​​безмозглую систему выполнения, что она не сможет обрабатывать отрицательные числа с плавающей запятой.Мне кажется гораздо более вероятным, что информация повреждена где-то еще (например, в процессе «печати», каким бы он ни был).

Другие советы

Есть ли у микроконтроллера аппаратное обеспечение для плавающей точки? Возможно нет; Микроконтроллеры обычно нет. Таким образом, это может быть ошибкой или ограничением в реализации программного обеспечения арифметики с плавающей точкой. Ищите документацию и/или прочитайте источник, если он у вас есть.

Возможно ли, что вы пытаетесь распечатать результат 0,001 - 0,005 в качестве 5 -х поля персонажа? Если это так, результат будет отображаться как округление до 0,0.

Можете ли вы предоставить больше контекста? В этом примере оценка проходит компилятор, так как обе константы известны во время компиляции. Какой тип «результата»? (т.е. IEEE-754 Половина или одинока или вдвое?) Как вы это оцениваете? Использование отладчика, IF-Statement или с printf? Причина, по которой я спрашиваю, в том, что может быть красная сельдь. Например, если вы форматируете неправильно с помощью printf, вы можете просто не увидеть знак минус. Когда вы посмотрите на двоичное представление (т.е. от Printf («%lx», результат), если оно 32-битное) и проверьте бит знака.

Это не является по своей сути C, так что это связано с вещами, которые вы не сказали:-

  • Контроллер (ST10, очевидно)
  • Компилятор (космическое программное обеспечение? Если да, то соответствует стандартам)
  • Библиотека с плавающей запятой (от компилятора?)
  • Программа (кратчайшая полная программа, которая демонстрирует, что это было бы хорошо.)

Может ли это быть ваш актерский состав, преобразующий из плавающей точки в INT, который вы не показали?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top