Sobes.tech
Middle

Могат ли да се използват числа с плаваща запетая като ключове на контейнери?

sobes.tech AI

Отговор от AI

Не се препоръчва.

Причини:

  1. Проблеми с сравняването: Числата с плаваща запетая не винаги могат да бъдат точно представени в двоичен формат. Сравнението за точно равенство a == b може да даде фалшив резултат поради грешки в представянето. Контейнерите, базирани на дървета (като асоциативни масиви, множества) и хеш таблиците, разчитат на точно сравнение или на изчисление на хеш въз основа на точна стойност.
  2. Нестабилност на хеша: Стойността на хеша на число с плаваща запетая, изчислена въз основа на неговото двоично представяне, няма да бъде стабилна при малки промени в стойността. Близки по стойност числа могат да имат много различни хешове, а еднакви по стойност числа (получени чрез различни изчисления поради грешки) могат да имат различни хешове. Това намалява ефективността на хеш таблиците (например std::unordered_map).
  3. Поведение на NaN и Infinity: Специалните стойности (NaN, Infinity) имат неопределено или нестандартизирано поведение при сравнение и хеширане, което може да доведе до непредсказуеми резултати.

Вместо това може да се използва:

  • Целочислено представяне, ако е приложимо (например, съхраняване на стойности в стотни).
  • Специализирани класове за сравнение или хеширане с вземане предвид на допустима грешка (epsilon), но това усложнява използването на стандартните контейнери.
  • boost::float_column, ако се използва библиотеката Boost.

Пример за проблем с сравняването:

#include <iostream>

int main() {
    double a = 0.1 + 0.2;
    double b = 0.3;
    if (a == b) {
        std::cout << "0.1 + 0.2 == 0.3" << std::endl; // Може да не се покаже
    } else {
        std::cout << "0.1 + 0.2 != 0.3 (заради грешка в точността)" << std::endl;
    }
    return 0;
}