map<double, double>
От: Аноним  
Дата: 02.01.03 15:51
Оценка:
Есть такой код:

#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
...

Скажете, что у меня не галлюцинации!!!??? где вкралась ошибка? помогите!
Re: map<double, double>
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 02.01.03 16:09
Оценка:
    std::cout << "lower: " << it2.first->first;
    std::cout << " upper: " << it2.first->second << std::endl;
Алексей Кирдин
Re[2]: map<double, double>
От: Bell Россия  
Дата: 02.01.03 16:14
Оценка:
Здравствуйте, Kaa, Вы писали:

Kaa>
Kaa>    std::cout << "lower: " << it2.first->first;
Kaa>    std::cout << " upper: " << it2.first->second << std::endl;
Kaa>


Это вывод пары ключ — значение. Но суть вопроса не в этом.
Любите книгу — источник знаний (с) М.Горький
Re[2]: map<double, double>
От: Аноним  
Дата: 02.01.03 16:22
Оценка:
Здравствуйте, Kaa, Вы писали:

Kaa>
Kaa>    std::cout << "lower: " << it2.first->first;
Kaa>    std::cout << " upper: " << it2.first->second << std::endl;
Kaa>


на консоль должны выводятся ключи, а не их значения (так задумано)
it2.first->first — lower ключ
it2.first->second — lower значение
it2.second->first — upper ключ
it2.second->second — upper значение

если value есть в множестве, то ключи должны отличаться на единицу,
очевидно, что ключ 0.8 (0.9, 1,...) есть в множестве, однако программа с этим не согласна почему-то
Re: map<double, double>
От: Bell Россия  
Дата: 02.01.03 16:31
Оценка:
Здравствуйте, Аноним, Вы писали:

Прикол в том, что 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));
Любите книгу — источник знаний (с) М.Горький
Re[3]: map<double, double>
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 02.01.03 16:37
Оценка:
Невнимательно прочитал, извиняюсь.

Все дело в представлении чисел с плавающей точкой. Образно говоря, их нельзя сравнивать. Например, константа (как в твоем примере) с выражением, которое в идеальном мире равно значению той-же константы, могут быть не равны. (см. Q145889, к примеру)

Посему, во многих приложениях, где числа не очень длинный хвост имеют, и по ним еще и искать надо, представление в виде числа с плавающей точкой заменяется на представление целочисленное или около того, но так, чтоб избежать неоднозначности (так, к примеру, числа с двумя разрядами после запятой хранятся в Excel).
Алексей Кирдин
Re: map<double, double>
От: Left2 Украина  
Дата: 02.01.03 17:10
Оценка:
Сделай свой функтор для сравнения который будет сравнивать след. образом:
Из первого числа вычитается второе, затем разница берётся по модулю и сравнивается с маленьким числом (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?
Re[3]: map<double, double>
От: Left2 Украина  
Дата: 03.01.03 07:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Можно ли как-нибудь аргументировать выбор "маленького числа", почему 1e-9, а не 1e-308?


Возьми ту точность которая тебе нужна и поставь
Естественно, эта точность должна быть меньше чем точность double
Re[4]: map<double, double>
От: retalik www.airbandits.com/
Дата: 04.01.03 03:51
Оценка: 5 (1)
Здравствуйте, Left2, Вы писали:

L>Возьми ту точность которая тебе нужна и поставь

L>Естественно, эта точность должна быть меньше чем точность double

Именно для этого и существуют константы FLT_EPSILON и DBL_EPSILON.
Успехов,
Виталий.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.