Перейти к содержанию
    

sprintf Форматированный вывод отрицательных чисел

Здравствуйте форумчане!

Такой вопрос у меня как правильно преобразовать целочисленное знаковое число в строку без преобразования во float.

Имеем переменную int16_t current; 

Она соответствует физическому значению измеряемого тока следующим образом:

32767 = 3,2767A
-32768 = -3,2768A

Есть необходимость преобразовать это в форматированную строку вида:

I= 3,277A
I=-3,277A

Использую функцию sprintf, но она хорошо работает только для положительных чисел и чисел менее -10000 (менее -1.000A)

sprintf(Str_Buffer, "I= %1d.%03d A", current/10/1000, current/10%1000);

При значении например -0.623A этот код отдаст строку "0.-623", а не "-0.623"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Знак отдельно печатайте:

char sign = i < 0 ? '-' : ' ';
if (i < 0) i = -i;
sprintf(buf, "I= %1c%1d.%03d A", sign, current/10000, (current/10)%1000);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проще взять и написать самому  с нуля функцию, формирующую нужную строку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вместо последовательности /...% лучше использовать функцию div().

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Цитата

Использую функцию sprintf, но она хорошо работает только для положительных чисел и чисел менее -10000 (менее -1.000A)

Функция не при чём, просто Вы не умеете ею пользоваться. Всё легко и просто:

s16 current;
int i = current;
char c = '+';
if (i < 0) {
  c = '-';
  i = -i;
}
uint j = (uint)i / 10000u;
sprintf(..., "I= %c%u.%04u A", c, j, (uint)i - j * 10000u);
//возможно для AVR-компилятора int/uint лучше заменить на short/ushort - не знаю, не пользуюсь

 

5 часов назад, AHTOXA сказал:

Знак отдельно печатайте:


char sign = i < 0 ? '-' : ' ';
if (i < 0) i = -i;
sprintf(buf, "I= %1c%1d.%03d A", sign, current/10000, (current/10)%1000);

 

То, что Вы не знаете математики, нам уже давно известно, но всё таки - такое количество ляпов в 3-х строчках! - это должно быть слишком даже для Вас....  :unknw:

PS: А вообще: Ваш пример - пожалуй неплохой способ сделать как можно более тормозной код  :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, jcxz сказал:

То, что Вы не знаете математики, нам уже давно известно, но всё таки - такое количество ляпов в 3-х строчках! - это должно быть слишком даже для Вас....  :unknw:

Что, Славик, соскучился? :-) Ну давай, обосновывай свои наезды.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 hours ago, AHTOXA said:

Знак отдельно печатайте:

О, огромная благодарность все так просто, я был слеп когда смотрел на форматы sprintf :yahoo:

10 hours ago, aaarrr said:

Вместо последовательности /...% лучше использовать функцию div().

Спасибо! Переписал это так:

int16_t current;
char sign;
div_t fracDigit;

        if (current >= 0) sign = ' ';
        else sign = '-';
fracDigit = div(current/10, 1000);
sprintf(Str_Buffer, "I= %1c%1d.%03d A", sign, fracDigit.quot, fracDigit.rem);

 

5 hours ago, jcxz said:

Функция не при чём, просто Вы не умеете ею пользоваться.

Именно поэтому я и написал в раздел "В помощь начинающему" на форуме. Спасибо, идея аналогична первому ответу и в данной задаче сверх-оптимизация не требуется.

10 hours ago, rkit said:

Проще взять и написать самому  с нуля функцию, формирующую нужную строку.

Возможно кому-то и проще.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 минуты назад, ToR_TDA сказал:

Именно поэтому я и написал в раздел "В помощь начинающему" на форуме. Спасибо, идея аналогична первому ответу и в данной задаче сверх-оптимизация не требуется.

Дело не в оптимизации - это мелочи. В "первом ответе" куча ляпов и багов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, jcxz said:

Дело не в оптимизации - это мелочи. В "первом ответе" куча ляпов и багов.

Но идея то правильная:smile:  Я не из тех кто выбивает от людей на форуме готовый исполняемый код, мне нужна была лишь подсказка. И теперь все работает как нужно:biggrin:, еще раз спасибо всем за ответы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 минут назад, ToR_TDA сказал:

Но идея то правильная:smile:  Я не из тех кто выбивает от людей на форуме готовый исполняемый код, мне нужна была лишь подсказка. И теперь все работает как нужно:biggrin:, еще раз спасибо всем за ответы.

Вы уверены что он действительно "работающий"?  :wink:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, jcxz said:

Вы уверены что он действительно "работающий"?  :wink:

Да, я проверил все в железе на всем диапазоне несколько раз. Форматирование работает корректно.

1.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, ToR_TDA сказал:

Форматирование работает корректно

Славик вам намекает, что int16_t несимметричный - отрицательному значению -32768 нет соответствующего положительного. Это надо учесть при смене знака числа - либо преобразовать его в int32_t, либо менять знак уже после деления на 10/1000.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 minutes ago, AHTOXA said:

Это надо учесть при смене знака числа

Если честно то не очень понял. Есть некоторое АЦП которое отдает мне данные так:

12 hours ago, ToR_TDA said:

32767 = 3,2767A
-32768 = -3,2768A

При этом коду 0x0000 соответствует ток 0А. В какой момент происходит неправильная смена знака?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 минуту назад, AHTOXA сказал:

Славик вам намекает, что int16_t несимметричный

До Андрюши похоже дошло.... Ну лучше поздно чем никогда.  :unknw:

 

25 минут назад, ToR_TDA сказал:

Да, я проверил все в железе на всем диапазоне несколько раз. Форматирование работает корректно.

Хозяин - барин. Ваш проект - вам виднее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 minutes ago, jcxz said:

Хозяин - барин. Ваш проект - вам виднее.

Не не не, если уж сказали то договаривайте, вот код который работает сейчас:

int16_t current;
char sign;
div_t fracDigit;

        if (current >= 0) sign = ' ';
        else sign = '-';
fracDigit = div(current/10, 1000);
sprintf(Str_Buffer, "I= %1c%1d.%03d A", sign, fracDigit.quot, fracDigit.rem);

В какой момент происходит проблема? И почему я не вижу ее по показаниям?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...