#include <iostream>
#include <map>
const double value = 0.7;
int main() {
typedef std::map<double, double> MR2; MR2 mr2;
for (double d = 0; d < 100; d += 0.1) mr2.insert(std::make_pair(d, d * 10));
std::pair<MR2::iterator, MR2::iterator> it2 = mr2.equal_range(value);
std::cout << "lower: " << it2.first->first;
std::cout << " upper: " << it2.second->first << std::endl;
return 0;
}
На выходе: lower: 0.7 upper: 0.8 логично!
Для value = 0... 0.7 все работает правильно, но если value в проге сделать равным 0.8 или больше, получим (для 0.8)
lower: 0.9 upper: 0.9
(для 0.9)
lower: 1 upper: 1
...
Скажете, что у меня не галлюцинации!!!??? где вкралась ошибка? помогите!
на консоль должны выводятся ключи, а не их значения (так задумано)
it2.first->first — lower ключ
it2.first->second — lower значение
it2.second->first — upper ключ
it2.second->second — upper значение
если value есть в множестве, то ключи должны отличаться на единицу,
очевидно, что ключ 0.8 (0.9, 1,...) есть в множестве, однако программа с этим не согласна почему-то
Прикол в том, что 0.1 представляется с некоторой погрешностью. При вычислении ключа (d) эта погрешность накапливается. Отсюда и проблемы.
Заполняй свой map так:
double dStep = 0.1;
for(int i = 0; i < 1000; ++i)
mr2.insert(std::make_pair(dStep*i, dStep*i*10));
Все дело в представлении чисел с плавающей точкой. Образно говоря, их нельзя сравнивать. Например, константа (как в твоем примере) с выражением, которое в идеальном мире равно значению той-же константы, могут быть не равны. (см. Q145889, к примеру)
Посему, во многих приложениях, где числа не очень длинный хвост имеют, и по ним еще и искать надо, представление в виде числа с плавающей точкой заменяется на представление целочисленное или около того, но так, чтоб избежать неоднозначности (так, к примеру, числа с двумя разрядами после запятой хранятся в Excel).
Сделай свой функтор для сравнения который будет сравнивать след. образом:
Из первого числа вычитается второе, затем разница берётся по модулю и сравнивается с маленьким числом (10^-9) например
Если разница меньше — значит числа равны (возвращаем false), иначе возвращаем результат обыкновенного сравнения double-ов
Re[2]: map<double, double>
От:
Аноним
Дата:
02.01.03 17:25
Оценка:
Здравствуйте, Left2, Вы писали:
L>Сделай свой функтор для сравнения который будет сравнивать след. образом: L>Из первого числа вычитается второе, затем разница берётся по модулю и сравнивается с маленьким числом (10^-9) например
СПАСИБО всем! т.о. (0.8 < 0.8) не факт false
Можно ли как-нибудь аргументировать выбор "маленького числа", почему 1e-9, а не 1e-308?