![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
Dmi3ev |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1698 Регистрация: 28.11.2007 Репутация: 1 Всего: 41 |
Столкнулся с такой проблемой: беру число (тип переменной double), например 0,03, это число сложно представить в двоичной системе(комп ведь в ней работает) (что-то вроде если 1/3 в десятичной представлять, то период получится), поэтому после некоторых действий оно либо немного больше, либо немного меньше того числа, которое получается на самом деле. Я написал свою функцию, которая, так сказать, округляет это дело, как мне надо. Но, интересно, можно это сделать как-нибудь по умному? Подскажите, пожалуйста. Или я заблуждаюсь на счет того, что это из-за двоичной системы счисления?
-------------------- |
|||
|
||||
bronislav |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 334 Регистрация: 29.1.2008 Где: Украина::Донецк Репутация: нет Всего: 3 |
Все вычисления на компьютере идут с округлением, когда нельзя посчитать точно. А числа с плавающей точкой в двоичной системе счисления представляются отдельно целаю часть, отдельно дробная. А в памяти компьютера записываются еще интересней. -------------------- ![]() иногда проще и быстрей обойти лужу, даже если кажется что она мелкая и путь напрямик короче - ведь она может скрывать открытый люк (с) mes |
|||
|
||||
Ken |
|
|||
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 31.3.2007 Репутация: 2 Всего: 4 |
Можете работать прямо с рациональными числами, например, опередлить класс Rational, переопределить арифметические операции и перобразование к типу double и т.д.
|
|||
|
||||
Dmi3ev |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1698 Регистрация: 28.11.2007 Репутация: 1 Всего: 41 |
это я понимаю, но, если я после некоторых операций должен получить в дробной части 0,12, то я получаю 0,119999..., причем, это происходит, когда в целой части большое число, например, 123456. вообщем, какая-то ерунда. я поэтому и спрашиваю. -------------------- |
|||
|
||||
Ken |
|
|||
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 31.3.2007 Репутация: 2 Всего: 4 |
Из за ограниченности количество разрядов для представления чисел в памяти вы часто получете такие ошибки. Поэтому вам надо все время округлять результат до какой-то точности. Из за этого даже операция проверки чисел с плавающей запятой на равенство часто дает неверный результат. Т.е. нельзя использовать запись типа a == b для таких типов. Это сообщение отредактировал(а) Ken - 24.5.2008, 10:05 |
|||
|
||||
Dmi3ev |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1698 Регистрация: 28.11.2007 Репутация: 1 Всего: 41 |
Ken, можно и так решить проблему (я функцию написал, ты класс предлагаешь), но, наверняка, есть способ, который до нас придуман, я и хочу узнать его.
-------------------- |
|||
|
||||
bronislav |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 334 Регистрация: 29.1.2008 Где: Украина::Донецк Репутация: нет Всего: 3 |
Способ был предложен выше. Использовать свой класс для таких расчетов и там реализовать необходимую точность.
-------------------- ![]() иногда проще и быстрей обойти лужу, даже если кажется что она мелкая и путь напрямик короче - ведь она может скрывать открытый люк (с) mes |
|||
|
||||
Ken |
|
|||
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 31.3.2007 Репутация: 2 Всего: 4 |
Если нужно представление рационального числа со 100% точностью, то способ один: хранить в виде пар чисел. На счет класса, я попробую предложить пример реализации. Пока, если вам просто надо сравнивать 2 числа на (примерное) равенство пишите так: abs (a - b) < epsilon здесь a и b числа с плавающей запятой, а epslion погрешность (положительное число ближу к 0). Это сообщение отредактировал(а) Ken - 24.5.2008, 10:28 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Да, это не из за двоичной системы счисления, а в из за способа представления числа в памяти. используйте тип с фиксированной запятой |
|||
|
||||
Ken |
|
|||
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 31.3.2007 Репутация: 2 Всего: 4 |
И так, обещал представить решение, но кажется до нас это уже сделали и несколько раз. Смотрите сюда: http://www.geekpedia.com/tutorial222_Overl...onal-Class.html http://solarix.ru/for_developers/cpp/boost.../rational.shtml |
|||
|
||||
bronislav |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 334 Регистрация: 29.1.2008 Где: Украина::Донецк Репутация: нет Всего: 3 |
Вот это решение мне нравиться больше. -------------------- ![]() иногда проще и быстрей обойти лужу, даже если кажется что она мелкая и путь напрямик короче - ведь она может скрывать открытый люк (с) mes |
|||
|
||||
ksili |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2069 Регистрация: 3.11.2005 Где: Красноярск Репутация: 1 Всего: 17 |
Можно задать режим округления чисел. Операции с вещественными числами выполняет FPU (Floating point unit) поэтому этот режим задается в его флагах. Всего там 4 режима:
к нулю к минус бесконечности к плюс бесконечности к ближайшему числу Наверняка ваш компилятор сам задает какой-то режим по -умолчанию. Как задать режим на ассемблере мне понятно, могу посмотреть как именно и позже написать (можете сами посмотреть книгу Зубкова по асму в разделе про FPU). А вот на С++ не знаю. Возможно придётся делать ассемблерную вставку. -------------------- Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с) |
|||
|
||||
Dmi3ev |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1698 Регистрация: 28.11.2007 Репутация: 1 Всего: 41 |
спасибо за помощь всем, проблему считаю решенной, мы докопались до истины, а точнее вы)))
Ken, отдельное спасибо, больше всех старался))) -------------------- |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |