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

Настройка sprintf

fval = 1.299;
sprintf(buff, "%2.3f", fval);
USART_SendString(SYS_USART, buff);

В IAR честно печатает 1.299

В GCC округляет - 1.300.

Где там настроить чтоб не округлял?

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


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

Если ты хочешь точности до цифры - не используй числа с плавающей точкой. Они не для этого. С любыми компиляторами и любыми настройками будут возникать такие ситуации.

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


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

1 hour ago, rkit said:

Если ты хочешь точности до цифры - не используй числа с плавающей точкой. Они не для этого. С любыми компиляторами и любыми настройками будут возникать такие ситуации.

с числом все в порядке. мне его надо отобразить на дисплее, для этого перевожу в строку, при переводе sprintf его округляет.

например такое решение правильно отображает число в любом компиляторе

Spoiler

#define MAX_PRECISION	(10)
static const double rounders[MAX_PRECISION + 1] =
{
    0.5,		// 0
    0.05,		// 1
    0.005,		// 2
    0.0005,		// 3
    0.00005,		// 4
    0.000005,		// 5
    0.0000005,		// 6
    0.00000005,		// 7
    0.000000005,	// 8
    0.0000000005,	// 9
    0.00000000005	// 10
};

char * ftoa(double f, char * buf, int precision)
{
    char * ptr = buf;
    char * p = ptr;
    char * p1;
    char c;
    long intPart;

    // check precision bounds
    if (precision > MAX_PRECISION)
	precision = MAX_PRECISION;

    // sign stuff
    if (f < 0)
    {
	f = -f;
	*ptr++ = '-';
    }

    if (precision < 0)  // negative precision == automatic precision guess
    {
	if (f < 1.0) precision = 6;
	else if (f < 10.0) precision = 5;
	else if (f < 100.0) precision = 4;
	else if (f < 1000.0) precision = 3;
	else if (f < 10000.0) precision = 2;
	else if (f < 100000.0) precision = 1;
	else precision = 0;
    }
                          
    // round value according the precision
    if (precision)
	f += rounders[precision];

    // integer part...
    intPart = (int)f;
    f -= intPart;

    if (!intPart)
	*ptr++ = '0';
    else
    {
	// save start pointer
	p = ptr;

	// convert (reverse order)
	while (intPart)
	{
	    *p++ = '0' + intPart % 10;
	    intPart /= 10;
	}

	// save end pos
	p1 = p;

	// reverse result
	while (p > ptr)
	{
	    c = *--p;
	    *p = *ptr;
	    *ptr++ = c;
	}

	// restore end pos
	ptr = p1;
    }

    // decimal part
    if (precision)
    {
	// place decimal point
	*ptr++ = '.';

	// convert
	while (precision--)
	{
	    f *= 10.0;
	    c = (char)f;
	    *ptr++ = '0' + c;
	    f -= c;
	}
    }

    // terminating zero
    *ptr = 0;

    return buf;
}

 

 

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


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

1 hour ago, jenya7 said:

де там настроить чтоб не округлял?

fval у вас какого типа? Ибо 1.299 это double, а 1.299f это флоат.

Полезная ссылка про формат IEEE-754.

Вряд ли что-то можно настроить. Библиотека каждого компилятора может немного по-другому обрабатывать числа. Это вполне допустимо.

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


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

1 hour ago, haker_fox said:

fval у вас какого типа? Ибо 1.299 это double, а 1.299f это флоат.

Полезная ссылка про формат IEEE-754.

Вряд ли что-то можно настроить. Библиотека каждого компилятора может немного по-другому обрабатывать числа. Это вполне допустимо.

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

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


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

19 minutes ago, jenya7 said:

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

Это вы fval объявили как float, а пытаетесь ему присвоить double, вот компилятор и производит преобразование типов при присваивании.

Чтобы этого избежать, к вашему значению 1.2999 надо добавить буковку f. Вот так

fval = 1.2999f;

 

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


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

1 hour ago, dimka76 said:

Это вы fval объявили как float, а пытаетесь ему присвоить double, вот компилятор и производит преобразование типов при присваивании.

Чтобы этого избежать, к вашему значению 1.2999 надо добавить буковку f. Вот так


fval = 1.2999f;

 

ааа. понял. спасибо.

правда тут я для примера поставил константное значение, реально это результат вычислений или fval = another_val. в таком случае нужен имплисит каст (float) несмотря на то что аргументы объявлены как float?

понял. нужно делать каст.

Изменено пользователем jenya7

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


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

1 hour ago, jenya7 said:

аргументы объявлены как float?

Какие аргументы?

Я уже выше вам написал, что

1.89 	// это double
1.89f 	// это float
7.88f   // это float
10.520  // это double
  
float abcd = 1.552f; // здесь компилятор присвоит константу типа флоат переменной типа флоат
float efgh = 7.410;  // здесь константа типа double будет присвоена переменной типа флоат, т.е. сначала будет вызвана процедура (программная) конвертации,
                     // а затем произойдёт присвоение

Рекомендую вам заглядывать в листинги. Там сразу увидите что к чему.

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


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

1 hour ago, haker_fox said:

Какие аргументы?

Я уже выше вам написал, что


1.89 	// это double
1.89f 	// это float
7.88f   // это float
10.520  // это double
  
float abcd = 1.552f; // здесь компилятор присвоит константу типа флоат переменной типа флоат
float efgh = 7.410;  // здесь константа типа double будет присвоена переменной типа флоат, т.е. сначала будет вызвана процедура (программная) конвертации,
                     // а затем произойдёт присвоение

Рекомендую вам заглядывать в листинги. Там сразу увидите что к чему.

понял.

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


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

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

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

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

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

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

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

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

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

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