Страница 1 из 2
функции округления в C.
Добавлено: 10 май 2007, 16:30
BBB
Что-то я затупил.
Какие есть в C функции округления дробного числа до целого? Типа
round в Delphi/Pascal.
Т.е. для того, чтобы значение из переменной типа
double преобразовать в переменную типа
long.
Можно, конечно, просто присвоением (компилятор ругается, но не ошибкой, а варнингом). Или через "преобразование типа":
Во втором случае даже варнинга нет. Но в обоих случаях значение не округляется, а происходит отсечение дробной части. Т.е. если dbl = 4.5555, то результат получается неа 5, а 4.
Заранее спасибо.
Re: функции округления в C.
Добавлено: 10 май 2007, 19:27
Absurd
в с никто не округляет даблы. а зачем это тебе нужно?
Re: функции округления в C.
Добавлено: 10 май 2007, 20:43
Romeo
Absurd, это нужно в милионе случаев. Например при работе с графикой, когда нужно значение коррдинаты, которое хранится в double, округлить к целому, ведь точки на экране дискретные.
BBB, воспользуйся формулой (long)(dSomeDouble + 0.5) - будет работать анологично паскалевскому round.
Re: функции округления в C.
Добавлено: 10 май 2007, 21:26
Absurd
Romeo писал(а):Absurd, это нужно в милионе случаев. Например при работе с графикой, когда нужно значение коррдинаты, которое хранится в double, округлить к целому, ведь точки на экране дискретные.
BBB, воспользуйся формулой (long)(dSomeDouble + 0.5) - будет работать анологично паскалевскому round.
Округлять обычно надо только при выводе пользователю в удобоваримом формате и для этого есть sprintf(...).
Для графики совершенно монопенисуально - будешь ли ты отбрасывать дробную часть или делать "математически корректно" - результат будет один и тот же поскольку пикселя бывают только целые.
Re: функции округления в C.
Добавлено: 11 май 2007, 10:24
BBB
Romeo писал(а):Absurd, это нужно в милионе случаев. Например при работе с графикой, когда нужно значение коррдинаты, которое хранится в double, округлить к целому, ведь точки на экране дискретные.
Ага, именно. Конечно, в таком случае "округление" до целой части вместо округления по математическим правилам не приведет к каким-то фатальным последствиям, но, как говорится, на душе будет теплее, если получится чуть точнее
BBB, воспользуйся формулой (long)(dSomeDouble + 0.5) - будет работать анологично паскалевскому round.
Спасибо. Я как-то в этом направлении и стал рассуждать.
Но все равно удивительно, что в C нет такой, казалось бы, базовой арифметической функции.
Absurd писал(а):Для графики совершенно монопенисуально - будешь ли ты отбрасывать дробную часть или делать "математически корректно" - результат будет один и тот же поскольку пикселя бывают только целые.
Странный вывод. Именно потому, что "пикселя бывают только целые" результат отброса дробной части и "округления математически корректно" в статистически половине случаев будет отличаться друг от друга на единицу. Может, как писал выше в этом сообщении, это и не приведет фатальным последствиям, но приятнее чувствовать, что ты получил чуть более точный результат.
Re: функции округления в C.
Добавлено: 11 май 2007, 12:24
Absurd
BBB писал(а):Но все равно удивительно, что в C нет такой, казалось бы, базовой арифметической функции.
Если бы была, то мы бы имели проблесы с каким - нибудь (м)чудаком который бы округлял промежуточный результат и терял разряды.
BBB писал(а):Странный вывод. Именно потому, что "пикселя бывают только целые" результат отброса дробной части и "округления математически корректно" в статистически половине случаев будет отличаться друг от друга на единицу. Может, как писал выше в этом сообщении, это и не приведет фатальным последствиям, но приятнее чувствовать, что ты получил чуть более точный результат.
Нет, более точный результат не получится, поскольку в обоих случаях мы имеем точность до пикселя: либо -0.5 <= x < 0.5 либо 0.0 <= x < 1.0. Это смещение будет компенсировано.
Погрешности
Добавлено: 11 май 2007, 12:41
BBB
Absurd писал(а):Нет, более точный результат не получится, поскольку в обоих случаях мы имеем точность до пикселя: либо -0.5 <= x < 0.5 либо 0.0 <= x < 1.0. Это смещение будет компенсировано.
Эээ.. Признаться, не очень понял, что ты имел в виду. Приведу свой пример.
Пусть "точная" координата (полученная в результате вычисления) равна, скажем, 6.7.
При мат.округлении до целого результат будет 7. При отбрасывании дробной части - 6. Где ошибка (погрешность) больше? Очевидно, что во втором случае.
Таким образом, при мат.округлении значение погрешности всегда будет пределах (по модулю):
0<= погр. <=0.5
А при отбрасывании дробной части в пределах:
0<= погр. < 1
Re: функции округления в C.
Добавлено: 11 май 2007, 13:10
BBB
Romeo писал(а):BBB, воспользуйся формулой (long)(dSomeDouble + 0.5) - будет работать анологично паскалевскому round.
Пришлось немного тоньше написать:
Код: Выделить всё
long Round (const double &dbl)
{
if (dbl >= 0)
return ((long)(dbl + 0.5));
else
return ((long)(dbl - 0.5));
};
Если применять просто
(long)(dSomeDouble + 0.5), то возникли забавности с отрицательными числами. Например, для -1.4 результат получался 0.
Re: функции округления в C.
Добавлено: 11 май 2007, 14:09
Romeo
BBB, с поправкой согласен - я просто принцип показал

.
Absurd, я тоже не понял твоего примера. Округление даёт меньшую погрешность, чем выделение целой части - это факт. А ты спорить пытаешься

.
Re: Погрешности
Добавлено: 11 май 2007, 14:24
Absurd
BBB писал(а):Эээ.. Признаться, не очень понял, что ты имел в виду. Приведу свой пример.
Пусть "точная" координата (полученная в результате вычисления) равна, скажем, 6.7.
При мат.округлении до целого результат будет 7. При отбрасывании дробной части - 6. Где ошибка (погрешность) больше? Очевидно, что во втором случае.
Объяснаю на пальцах. При отбрасывании дробной части крайний левый пиксель имеет покрытие значений 0.0 <= x < 1.0. При округлении к ближайшему целому - 0.0 <= x < 0.5. В то время как второй пиксель имеет покрытие в два раза шире : 0.5 <= x < 1.5. Если же поместить "(0 , 0)" координатной сетки в центр окна то ситуация не изменится так как ты уже заметил что отбрасывание дробной части у -0.5 дает -1.