Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Проблемы с отбрасыванием дробной части


Автор: Cheese 22.7.2009, 18:55
Суть проблемы: надо из double сделать int, убрав дробную часть. Казалось, бы всего ничего, преобразовать в int, но не работает, причём выдаёт воистину чудовищный результат: 6.000000 превращается в 5. Подозреваю, что тут что-то с точностью, так как если сделать не double а long double проблема исчезает. На некоторое время, потому что если взять число побольше, опять n превращается в n-1. Пробовал не (int) y, а floor(y) - та же проблема. 
Вот пример, чтобы не быть голословным:

Код

#include <stdio.h>
int main()
{
    int i;
    double y = 0;
    int dx = 5;
    int dy = 3;
    double k = (double) dy/dx;
    for ( i=0; i<11; i++, y+=k )
    printf( "y = %f, y_rounded = %i\n", y, (int) y );
}


Здесь формируется игрик, через складывание множества дробных чисел. При этом программа выдаёт:

Код

y = 0.000000, y_rounded = 0
y = 0.600000, y_rounded = 0
y = 1.200000, y_rounded = 1
y = 1.800000, y_rounded = 1
y = 2.400000, y_rounded = 2
y = 3.000000, y_rounded = 3
y = 3.600000, y_rounded = 3
y = 4.200000, y_rounded = 4
y = 4.800000, y_rounded = 4
y = 5.400000, y_rounded = 5
y = 6.000000, y_rounded = 5


Последняя строка убивает. Товарищи, в чём дело?
Работаю в линуксе, через gcc.

Автор: Фантом 22.7.2009, 19:01
Ну да, проблема с точностью. Если нужно так обрабатывать только числа, фактически являющиеся целыми, то просто прибавляйте 0.5 перед отбрасыванием дробной части.

Автор: Леопольд 22.7.2009, 21:47
Цитата(Cheese @ 22.7.2009,  18:55)
Код

...
y = 6.000000, y_rounded = 5


Последняя строка убивает. Товарищи, в чём дело?
Работаю в линуксе, через gcc.

Похоже на то что printf округляет значение. Выглядит правдоподобно, если, например, y = 5.9999999

Я угадал. Попробуй это:
Код

#include <stdio.h>

int main()
{
    int i;
    double y = 0;
    int dx = 5;
    int dy = 3;
    double k = (double) dy/dx;
    for ( i=0; i<11; i++, y+=k )
    printf( "y = %.20f, y_rounded = %i\n", y, (int) y );
}


Правильнее будет сделать так:
printf( "y = %.20f, y_rounded = %.0f\n", y, y );

Автор: codelord 23.7.2009, 11:33
Код

#include <math.h>
long dround( double x )
{
        return (long)round(x);
}


Автор: PirateTigo 1.8.2009, 23:40
у Вас написано так:
Код

printf( "y = %.20f, y_rounded = %i\n", y, (int) y );


а если попробовать так:
Код

printf( "y = %.20f, y_rounded = %d\n", y, (int) y );


?

Автор: VC15 4.8.2009, 17:27
Да, дело здесь именно в том, что printf округляет. Поэтому на самом деле в y хранится 5.99999999, а выводится 6.0000. Чтобы избавиться от этой проблемы, я предлагаю использовать printf( "y = %f, y_rounded = %i\n", y, int(y + 1e-9) );

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)