Russian Qt Forum
Января 19, 2025, 23:43 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Неожиданный результат при делении (1.0/10.0=0.10000000000000001 ?????????)  (Прочитано 12673 раз)
Dimon-st
Гость
« : Июля 19, 2010, 13:29 »

Всем привет !
Столкнулся с банальной, но неприятной и неразрешимой (пока) ситуацией при простой операции деления с вещественными числами.
Суть проблемы: при делении меньшего числа на большее число (по величине отличаются в 10 раз) результат получается: "0.10000000000000001" (и при отладке и при при прогоне программы). Причем результат не зависит от типа вещественных данных (пробовал qreal, double, long double).
Вот фрагмент кода:
Код:
double vX, vY, vRez;

vX=1.0;
vY=10.0;

vRez=vX/vY;

Кроме того, при принудительном присваивании переменной значения "vX=0.1;", результат получается "vX=0.10000000000000001".  Шокированный  Непонимающий
Код:
long double vX;

vX=0.1;


Пробовал округлять, но при нем вываливается тот же косяк....
У меня нет больше вариантов как с этим бороться .....

Использую Qt Creator (Qt 4.7.0 (32-битн.)) от Nokia Corp.
Пожалуйста, помогите ! Плачущий
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #1 : Июля 19, 2010, 14:24 »

Для вещественных чисел это обычная погрешность.

для сравнения используй
Код:
if (fabs(a - b) < 1e-6)
{
     return true;
}esle
     return false;
Записан
Wlad_C
Гость
« Ответ #2 : Июля 19, 2010, 14:25 »

С чем бороться?
То, что Вы получаете - так и должно быть!
Это происходит при переводе из двоичной системы в десятичню. Можете проверить ручками!
Записан
Dimon-st
Гость
« Ответ #3 : Июля 19, 2010, 14:39 »

Цитировать
С чем бороться?
То, что Вы получаете - так и должно быть!
Это происходит при переводе из двоичной системы в десятичную. Можете проверить ручками!

Я допускаю такое при делении, но при присваивании Непонимающий?
Код:
long double vX;

vX=0.1;

при выполнении этого фрагмента получается "vX=0.10000000000000001".
Может у кого по другому? Отпишитесь .....
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #4 : Июля 19, 2010, 14:50 »

Боюсь что нет Улыбающийся Это нормально вроде как  Улыбающийся а какие трудности в вязи с этим?
Записан
Dimon-st
Гость
« Ответ #5 : Июля 19, 2010, 15:10 »

Да, проблемы есть.
Разрабатываю класс, и в одном (именно этом) случае, он лагает. Грустный
Имеется 4 числа: начальное,  конечное значения, шаг и количество: vFirstValue, vLastValue, vStep, vCount.
Изменяя одно из значений, пересчитываются остальные (или одно из них). При следующих данных:
vLastValue=10, vFirstValue=0
задаем: vCount=101
и пересчитываем vStep и vFirstValue
Получаю
vStep=0.10000000000000001
vFirstValue=-5.55112e-16

Хотя, по идее должно быть:
vStep=0.1
vFirstValue=0

Как этого добиться ?
Записан
SimpleSunny
Гость
« Ответ #6 : Июля 19, 2010, 16:20 »

"-5.55112e-16" можно сказать, что 0. Какая проблема?
Записан
Sancho_s_rancho
Гость
« Ответ #7 : Июля 19, 2010, 17:42 »

Код:
qFuzzyCompare ( double p1, double p2 )   [static]
вам поможет. Прочтите в документации.
И обратите внимание на
Код:
// Instead of comparing with 0.0
                 qFuzzyCompare(0.0,1.0e-200); // This will return false
         // Compare adding 1 to both values will fix the problem
                 qFuzzyCompare(1 + 0.0, 1 + 1.0e-200); // This will return true
Записан
Dimon-st
Гость
« Ответ #8 : Июля 19, 2010, 18:51 »

Цитировать
"-5.55112e-16" можно сказать, что 0. Какая проблема?
Проблема в том, что именно так он выдает и при преобразовании числа в стоку (без форматирования), хотя хотелось бы "0".

Сравнение чисел в данном алгоритме не подходит
Цитировать
qFuzzyCompare(0.0,1.0e-200);


Пробовал принудительно так:
Код:
    if (vStep!=10.0)
        {
         vStep=1.0/vStep;
        }
        else
            {
            vStep=1.0e-1;
            }
но при попытке присвоить "vStep=1.0e-1;", значение оказывается "vStep=0.10000000000000001", но почему Непонимающий? Это же простое присваивание?

Программисты Qt, пожалуйста отпишитесь, у всех при отладке после банального присвоения "vStep=1.0e-1;" получается "vStep=0.10000000000000001"? Протестировал в BDS и MSVS2008, там все работает без всяких проблем. Не знаю что и думать, версия Qt у меня такая глючная, или я уже ничего не понимаю...
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #9 : Июля 19, 2010, 18:58 »

QString QString::number ( double n, char format = 'g', int precision = 6 )   [static]

Не вижу проблемы..

P.S. так вспомнилось:
Российским учёным первыми в мире
удалось раздуть из мухи слона  Смеющийся

« Последнее редактирование: Июля 19, 2010, 19:01 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июля 19, 2010, 19:01 »

В дополнение к сказанному

- др. отладчики также показывают подобным образом

- для чисел с конечным числом знаков после запятой равенство срабатывает, напр
Код:
float t = 1.0f;
t /= 10;
...
if (t == 0.1f) {   // вернет true
...
}

- пример c 1.0e-200 специфичен, насколько я помню: диапазон от 1.0e-38  до 1.0e+38 (для всех float, double и др., разница между ними в точности). Меньшие значения INF - не ноль, но и значение неизвестно

Edit: см. также недавнее обсуждение http://www.prog.org.ru/topic_14154_0.html  
« Последнее редактирование: Июля 19, 2010, 19:04 от Igors » Записан
Dimon-st
Гость
« Ответ #11 : Июля 19, 2010, 19:21 »

Цитировать
Российским учёным первыми в мире
удалось раздуть из мухи слона
Шутку оценил ! Но мне искренне не понятно: почему в BDS и MSVS код "1.0/10.0=0.1" работает без проблем, а в Qt банальное "x=1.0e-1;", приводит к "х=0.10000000000000001"? (получается риторический вопрос) Смеющийся

Как я понял от этого косяка не избавиться, единственное, что можно - воспользоваться округлением. Поэтому вопрос такой: есть ли какие стандартные функции округления, или придется извращаться через преобразование в строку и обратно "QString QString::number ( double n, char format = 'g', int precision = 6 )" ?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #12 : Июля 19, 2010, 19:40 »

Вы там что, поправку к сверхтонкой структуре считаете, чтоль?

Сейчас Вам кто-нить расскажет, что дело здесь вовсе не в кутэ.. Так что не надо крошить на Qt))

Ответ кроется в том, как представляются числа с плавающей точкой.. Спросите у гугла, как устроен double, например) 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Dimon-st
Гость
« Ответ #13 : Июля 19, 2010, 19:56 »

Цитировать
Ответ кроется в том, как представляются числа с плавающей точкой.. Спросите у гугла, как устроен double, например)
Я знаком со структурой double и float, и на Qt никто не "крошит". Просто неясно: если в BDS, MSVS и Qt структуры типов данных одинаковые, то почему результаты BDS, MSVS и Qt - разные ? Может это быть из-за того, что установленная у меня версия Qt Creator "кривая" ? Поэтому я и просил протестировать на др. компах небольшие фрагменты кода.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Июля 19, 2010, 20:18 »

Просто неясно: если в BDS, MSVS и Qt структуры типов данных одинаковые, то почему результаты BDS, MSVS и Qt - разные ?
Результаты - одинаковые и здесь и там. Просто "здесь" отладчик показывает с большей точностью - вот и все
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.028 секунд. Запросов: 23.