![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
Волод |
|
|||
Unregistered |
Братцы! Объясните дураку. Возникла у меня тут необходимость написать функцию округления чисел, и вдруг столнулся с проблемой – не округляет правильно некоторые числа и все тут!
Стал копаться, и увидел неожиданную фишку – емкости чисел типа float недостаточно для выполнения операции! Вот примеры:
То есть если целая часть числа содержит больше 4 разрядов, начинается округление дробной/целой части числа…. Я вначале даже не поверил, заглядываю в книгу – написано: платформа Win32, диапазон float: 3.4 e-38 … 3.4 e+38. То есть, если я правильно понял, минимум 38 разрядов числа должно у меня храниться нормально, у меня же, получается, уже 7 разрядов числа вызывают искажение. Работаю на VC 6++, в чем дело?.... |
|||
|
||||
mr.Anderson |
|
|||
![]() iOS Lead Developer ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3374 Регистрация: 20.12.2004 Где: далеко Репутация: нет Всего: 128 |
Как вы выводите результат на экран? Попробуйте вот такой код:
По-моему, так. |
|||
|
||||
Mayk |
|
||||
![]() ^аВаТаР^ сообщение>> ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2616 Регистрация: 22.5.2005 Где: за границей разум а Репутация: 45 Всего: 134 |
Не верно. Имей ты хоть трилиард знаков, ты не получишь 0.3 в точности: (переводим 0,3 в двоичную): 0, 3|x2 0, 6|x2 1, 2|x2 0, 4|x2 0, 8|x2 1, 6|x2 период. А вообще ну его этот флоат, юзай double. Или long double(80 бит).
То,что printf выводит 0.3 это исключительно заслуга printf'а ![]() -------------------- Здесь был кролик. Но его убили. Человеки < кроликов, йа считаю. |
||||
|
|||||
mr.Anderson |
|
|||
![]() iOS Lead Developer ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3374 Регистрация: 20.12.2004 Где: далеко Репутация: нет Всего: 128 |
Неплохо...
![]()
|
|||
|
||||
Волод |
|
|||
Unregistered |
Я вообще на экран результат не вывожу. Стал через отладчик смотреть, где ошибся в алгоритме округления, а тут на тебе - такие искажения уже на этапе присвоения, а вообще то я это число просто передаю, как аргумент, в функцию окруления. Майк, а можно поподробнее про твои выкладки, я не совсем понял, при чем туту перевод в двоичную систему....
|
|||
|
||||
Mayk |
|
||||
![]() ^аВаТаР^ сообщение>> ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2616 Регистрация: 22.5.2005 Где: за границей разум а Репутация: 45 Всего: 134 |
Искажения происходят при переводе из десятичной системы счисления в двоичную и обратно. Процессор работает с двоичной арифметикой, а число 12345.67 невозможно перевести в двоичную сс, так как при переводе получается бесконечная периодическая дробь. Что-то типа того, что на обычном калькуляторе выполнить 10/3*3. После выполнения не получится 10. Поэтому он вместо числа 12345.67 обрабатывает максимально приближенное к нему число. В двоичной системе 12345,67 будет выглядеть как 11000000111001.101010111000010100011110101110000101001.... В флоате под мантиссу отводится 24 бита(при этом первый бит не записывается, он равен 1), а теперь считаем. 14 бит будут отведены под целую часть(11000000111001. вот она целая часть в 14 битах). На дробную остаются каких-то жалких 10 битов. Вот и отсутствие точности. Используй double, он точнее. Или long double - он еще точнее. зы. Но всё равно странно. 12345.67 должно преобразоваться в 12345.669921875. Возможно отладчик округляет значение по своему усмотрению. Попробуй
и посмтори чему равна s. Это сообщение отредактировал(а) Mayk - 20.8.2005, 19:50 -------------------- Здесь был кролик. Но его убили. Человеки < кроликов, йа считаю. |
||||
|
|||||
Волод |
|
|||
Unregistered |
Спасибо за пояснения, видимо придется работать с double. Теперь я , по крайней мере, понимаю, почему стандартные функции округления типа ceil и floor тоже работают с double, а не float
|
|||
|
||||
RVN |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 4.2.2005 Где: Россия Репутация: нет Всего: нет |
Попробуй так
код C++ double X=123,455555555; X=RoundTo(X,-2);// X=123,46 И по-моему все равно double или float |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |