Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите разобраться с float 
:(
    Опции темы
Волод
Дата 20.8.2005, 16:22 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Братцы! Объясните дураку. Возникла у меня тут необходимость написать функцию округления чисел, и вдруг столнулся с проблемой – не округляет правильно некоторые числа и все тут!
Стал копаться, и увидел неожиданную фишку – емкости чисел типа float недостаточно для выполнения операции! Вот примеры:
Код

float summ=1234.56;    //summ=1234.56
float summ=12345.67;    //summ=12345.70
float summ=123456.78;    //summ=123457

То есть если целая часть числа содержит больше 4 разрядов, начинается округление дробной/целой части числа…. Я вначале даже не поверил, заглядываю в книгу – написано: платформа Win32, диапазон float: 3.4 e-38 … 3.4 e+38. То есть, если я правильно понял, минимум 38 разрядов числа должно у меня храниться нормально, у меня же, получается, уже 7 разрядов числа вызывают искажение. Работаю на VC 6++, в чем дело?....

  Вверх
mr.Anderson
Дата 20.8.2005, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: нет
Всего: 128



Как вы выводите результат на экран? Попробуйте вот такой код:
Код

//Тут вы создаете, предположим, переменную VAR, содержащую округленное значение.
...
//А теперь выводим результат:
printf("Результат: %.5f",VAR);

По-моему, так.


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 20.8.2005, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата
минимум 38 разрядов числа должно у меня храниться нормально

Не верно. Имей ты хоть трилиард знаков, ты не получишь 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 бит).

Цитата(sim7 @ 20.8.2005, 20:51)
printf("Результат: %.5f",VAR);

То,что printf выводит 0.3 это исключительно заслуга printf'а smile


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 20.8.2005, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: нет
Всего: 128



Неплохо... smile Только еще добавлю: чтобы double не выводилось как экспоненциальное число или с огромным количеством знаков после и/или до запятой, ограничивайте их через printf, как я описал в своем примере. Например, так:
Код

//Переменная VAR типа double, содержащая результат, объявляется тут. Где-то тут.
printf("Rezult: %.10f",VAR);




--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Волод
Дата 20.8.2005, 18:39 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Я вообще на экран результат не вывожу. Стал через отладчик смотреть, где ошибся в алгоритме округления, а тут на тебе - такие искажения уже на этапе присвоения, а вообще то я это число просто передаю, как аргумент, в функцию окруления. Майк, а можно поподробнее про твои выкладки, я не совсем понял, при чем туту перевод в двоичную систему....
  Вверх
Mayk
Дата 20.8.2005, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 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. Возможно отладчик округляет значение по своему усмотрению. Попробуй
Код

char s[50]; sprintf(s,"%.10f",summ); 

и посмтори чему равна s.

Это сообщение отредактировал(а) Mayk - 20.8.2005, 19:50


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Волод
Дата 21.8.2005, 05:53 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Спасибо за пояснения, видимо придется работать с double. Теперь я , по крайней мере, понимаю, почему стандартные функции округления типа ceil и floor тоже работают с double, а не float
  Вверх
RVN
Дата 13.9.2005, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 4.2.2005
Где: Россия

Репутация: нет
Всего: нет



Попробуй так
код C++
double X=123,455555555;
X=RoundTo(X,-2);// X=123,46
И по-моему все равно double или float
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1164 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.