Jump to content

    

Recommended Posts

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

Share this post


Link to post
Share on other sites
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;
}

 

 

Share this post


Link to post
Share on other sites
1 hour ago, jenya7 said:

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

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

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

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

Share this post


Link to post
Share on other sites
1 hour ago, haker_fox said:

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

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

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

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

Share this post


Link to post
Share on other sites
19 minutes ago, jenya7 said:

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

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

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

fval = 1.2999f;

 

Share this post


Link to post
Share on other sites
1 hour ago, dimka76 said:

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

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


fval = 1.2999f;

 

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

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

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

Edited by jenya7

Share this post


Link to post
Share on other sites
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 будет присвоена переменной типа флоат, т.е. сначала будет вызвана процедура (программная) конвертации,
                     // а затем произойдёт присвоение

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

Share this post


Link to post
Share on other sites
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 будет присвоена переменной типа флоат, т.е. сначала будет вызвана процедура (программная) конвертации,
                     // а затем произойдёт присвоение

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

понял.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.