Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.65/20: Рейтинг темы: голосов - 20, средняя оценка - 4.65
rikimaru2013
C++ Game Dev
2472 / 1141 / 348
Регистрация: 30.11.2013
Сообщений: 3,709
1

Проблема сравнения чисел с плавающей точкой

25.04.2015, 01:48. Просмотров 4029. Ответов 22
Метки нет (Все метки)

Добрый вечер,

развивая тему к которой меня подтолкнул, Байт, посоветуйте ряд лайффаков на тему фикса (кроссплатформенность же ж )
C++
1
double x = 6.0/2; if(x == 3.0){}
C++
1
double a = 1.3; double b = 1.6; float c = 1.1; float d = 4.0; if(a+b+c == d) {}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.04.2015, 01:48
Ответы с готовыми решениями:

Написать защиту от ввода чисел с плавающей точкой, отрицательных чисел и символов
Привет всем! Вот пишу программу, преподаватель сказал чтобы написал защиту от...

Массив чисел с плавающей точкой
#include <iostream> #include <ctime> #include <fstream> using namespace std;...

Калькулятор чисел с плавающей точкой
double calculate(float x, char s, float y); int main() { float x,y;...

Форматирование чисел с плавающей точкой
Все знают про проблемы с представлением дробных чисел. Например: ...

Сравнение чисел с плавающей точкой
Известно, что числа с плавающей точкой нельзя сравнивать с помощью ==. Однако,...

22
zss
Модератор
Эксперт С++
7237 / 6692 / 4234
Регистрация: 18.12.2011
Сообщений: 17,654
Завершенные тесты: 1
25.04.2015, 08:57 2
Я пользуюсь таким методом:
C++
1
2
3
double x = 6.0/2.0;
double eps=1e-7;// по нужному количеству значащих цифр 
if( fabs(x - 3.0)<eps){}
2
Nick Alte
Эксперт С++
1647 / 1019 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
25.04.2015, 11:01 3
По моему опыту, может возникать 2 вида ситуаций: те, в которых лучше применять прямое сравнение, и те, в которых следует сравнивать приближённо.
Сразу можно сказать, что если ведутся какие-то вычисления (поиск корней методом деления, РК4 и вообще любые численные методы), приближённое сравнение единственный выход.
Прямое сравнение допустимо в тех случаях, когда, исходя из устройства вещественных чисел, мы имеем дело с заведомо "хорошими" числами, которые подвергаются очень небольшому числу "хороших". Например, целое число, только из-за того, что его перевели в формат float или double, не может получить дробный "довесок". Числа 1.1 и 1.31 "плохие", а 1.5 или 1.625 - "хорошие", деление на 3 - "плохое", а на 8 - "хорошее". Но обычно ситуации, в которых прямое сравнение допустимо, вообще не связаны с вычислениями как таковыми, а скорее возникают в ситуациях вроде разбора текстовых форматов.
0
rikimaru2013
C++ Game Dev
2472 / 1141 / 348
Регистрация: 30.11.2013
Сообщений: 3,709
25.04.2015, 15:17  [ТС] 4
Цитата Сообщение от Nick Alte Посмотреть сообщение
По моему опыту
я думал у старожил есть набор классов или define, которые решают такие проблемы
C++
1
 if( FloatingPoint::isEqual(3.14, a))
Или в продакшене не стаёт ребром вопрос про "проблему сравнения чисел с плавающей точкой"
0
Evg
25.04.2015, 18:17
  #5

Не по теме:

Я не алгоритмист, но в каких, например, алгоритмах, требуется сравнение на равенство вещественных чисел?

0
Kastaneda
25.04.2015, 21:34
  #6

Не по теме:

Цитата Сообщение от Evg Посмотреть сообщение
Я не алгоритмист, но в каких, например, алгоритмах, требуется сравнение на равенство вещественных чисел?
Вопрос именно об алгоритмах или о необходимости такого сравнения в целом? Если вообще, то реальный пример (правда мы это на Java пишет, но не суть) - есть некий веб сервис, туда приходят отчеты о неких финансовых операциях. В отчете перечень операций с указанием суммы конкретной операции, общая скидка, выраженная в процентах и общая сумма всех операций с учетом скидки. На сервере все суммируется, вычитается скидка и результат сравнивается с указанной общей суммой (just for check). Для таких вещей у нас есть самописный класс для различных float point операций, типа isEquals(), isLess() и т.д.

0
Somebody
25.04.2015, 21:48
  #7

Не по теме:

А я думал, финансовые операции с фиксированной точкой считают, знака 2-4 десятичных после запятой... А в математике вот с константами типа 0, 1 или Пи в геометрии сравнивать вполне может прийтись.

0
Kastaneda
25.04.2015, 22:04
  #8

Не по теме:

Somebody, написание своих MathUtils'ов уже на уровне рефлекса, не важно до какого символа после запятой требуется точность :) Хотя да, может не совсем хороший пример привел.

0
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
25.04.2015, 22:31 9
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
в продакшене
Смотря какой "продакшен". В Delphi, например, он не такой, как в C.

Округление

В разных сферах могут применяться различные методы округления
0
MrGluck
Модератор
Эксперт CЭксперт С++
8087 / 4940 / 1431
Регистрация: 29.11.2010
Сообщений: 13,398
25.04.2015, 23:41 10
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Или в продакшене не стаёт ребром вопрос про "проблему сравнения чисел с плавающей точкой"
Встаёт. В большинстве случаев сравнивают с заданной eps (обычно функция сравнения находится где-нибудь в Tools/Utilities). Но когда точности не хватает (у нас потребность возникла при самописном рисовании различных геом. объектов) используются готовые либы. Сейчас с ходу не вспомню название, но могу в понедельник глянуть на работе и написать.

Добавлено через 2 минуты
Цитата Сообщение от Evg Посмотреть сообщение
Я не алгоритмист, но в каких, например, алгоритмах, требуется сравнение на равенство вещественных чисел?
Сравнить ответ пользователя с результатом работы заданной функции.
1
Evg
Эксперт CАвтор FAQ
19288 / 7147 / 528
Регистрация: 30.03.2009
Сообщений: 20,000
Записей в блоге: 30
25.04.2015, 23:51 11
Цитата Сообщение от Kastaneda Посмотреть сообщение
В отчете перечень операций с указанием суммы конкретной операции, общая скидка, выраженная в процентах и общая сумма всех операций с учетом скидки. На сервере все суммируется, вычитается скидка и результат сравнивается с указанной общей суммой (just for check)
Да, это реальное применение, правда я всё равно толком не понял, зачем там сравнивать. Но по факту получается редко используемое, потому что доля всех прочих операций - весьма приличная

Цитата Сообщение от MrGluck Посмотреть сообщение
Сравнить ответ пользователя с результатом работы заданной функции
Я имел в виду в реальных приложениях, а не школьных заданиях
0
IrineK
Заблокирован
25.04.2015, 23:55 12
Цитата Сообщение от Evg Посмотреть сообщение
но в каких, например, алгоритмах, требуется сравнение на равенство вещественных чисел?
В численных методах (решение систем уравнений, дифуры) - сплошь и рядом. Без введенной (сознательно и с пониманием) точности вычислений не обойтись.
0
MrGluck
Модератор
Эксперт CЭксперт С++
8087 / 4940 / 1431
Регистрация: 29.11.2010
Сообщений: 13,398
25.04.2015, 23:58 13
Цитата Сообщение от Evg Посмотреть сообщение
Я имел в виду в реальных приложениях, а не школьных заданиях
Это реальное приложение, которое (по иронии судьбы) проверяет школьные задания.
0
Evg
Эксперт CАвтор FAQ
19288 / 7147 / 528
Регистрация: 30.03.2009
Сообщений: 20,000
Записей в блоге: 30
26.04.2015, 11:24 14
Цитата Сообщение от IrineK Посмотреть сообщение
В численных методах (решение систем уравнений, дифуры) - сплошь и рядом
Проверка на вхождение в диапазон - это я ещё понимаю, но где в численных методах нужно сравнение на точное равенство?

Цитата Сообщение от MrGluck Посмотреть сообщение
Это реальное приложение, которое (по иронии судьбы) проверяет школьные задания
Тут, строго говоря, сравнение скорее строковое, нежели вещественное
0
Kastaneda
26.04.2015, 12:16
  #15

Не по теме:

Цитата Сообщение от Evg Посмотреть сообщение
правда я всё равно толком не понял, зачем там сравнивать
На стороне партнера (откуда приходят эти данные) файл с транзакциями бывает составляет девочка-блондинка, поэтому к нам на сервер может прийти все, что угодно. Поэтому приходится все перепроверять.

0
Tulosba
:)
Эксперт С++
4749 / 3243 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
26.04.2015, 12:19 16
Цитата Сообщение от Nick Alte Посмотреть сообщение
Например, целое число, только из-за того, что его перевели в формат float или double, не может получить дробный "довесок".
Довесок может и не получит, но точность потерять легко.
http://coliru.stacked-crooked.com/a/28d4f3d1bb8a88c2
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
я думал у старожил есть набор классов или define, которые решают такие проблемы
Никакие классы тут не нужны, сравниваешь с заданной точность, как zss показал и всё.
0
Somebody
2799 / 1610 / 251
Регистрация: 03.12.2007
Сообщений: 4,213
Завершенные тесты: 3
26.04.2015, 12:44 17
Так-то да. Но double (IEEE'шный) - 53 бита. Если целое в них влезет, оно ничего не потеряет и не получит.
0
hoggy
Нарушитель
Эксперт С++
7087 / 3130 / 648
Регистрация: 15.11.2014
Сообщений: 7,209
Завершенные тесты: 1
26.04.2015, 12:46 18
Цитата Сообщение от IrineK Посмотреть сообщение
В численных методах (решение систем уравнений, дифуры) - сплошь и рядом. Без введенной (сознательно и с пониманием) точности вычислений не обойтись.

Не по теме:

есть массив дробных чисел (float или double, не суть)
как правильно сложить все эти числа так, что бы потери точности были минимальны?

0
Evg
26.04.2015, 12:50
  #19

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
есть массив дробных чисел (float или double, не суть)
как правильно сложить все эти числа так, что бы потери точности были минимальны?
Думаю, что надо отсортировать и складывать сначала числа с наименьшим модулем. Хотя на 100% не уверен

0
rikimaru2013
C++ Game Dev
2472 / 1141 / 348
Регистрация: 30.11.2013
Сообщений: 3,709
26.04.2015, 13:43  [ТС] 20
C++
1
2
3
4
5
bool isEqual2(double const first, double const second)
{
    static double eps = 1e-7;
    return fabs(first - second) < eps;
}
Подведём итоги. Пока что вижу такое решение, но оно слабое согласно статьи , и там же предлагают:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool AlmostEqual2sComplement(float A, float B, int maxUlps)
{
    // Make sure maxUlps is non-negative and small enough that the
    // default NAN won't compare as equal to anything.
    assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
    int aInt = *(int*)&A;
    // Make aInt lexicographically ordered as a twos-complement int
    if (aInt < 0)
        aInt = 0x80000000 - aInt;
    // Make bInt lexicographically ordered as a twos-complement int
    int bInt = *(int*)&B;
    if (bInt < 0)
        bInt = 0x80000000 - bInt;
    int intDiff = abs(aInt - bInt);
    if (intDiff <= maxUlps)
        return true;
    return false;
}
следовательно вызов AlmostEqual2sComplement(3.0, 6.0/2, 1);

но кажись вызов такой функции "накладное"
0
26.04.2015, 13:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.04.2015, 13:43

Умножения чисел с плавающей точкой
Доброго времени суток,нужна ваша помощь в умножение чисел с плавающей точкой....

Представление чисел с плавающей точкой
Никак не пойму почему в коде: double helper; bool cond; int...

Считывание из файла чисел с плавающей точкой
программа считывания из файла чисел в двумерный массив но как только в файле...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru