Sobes.tech
Junior

როგორ შევამოწმოთ ორი მყარი წერტილის (float) თანასწორობა?

sobes.tech AI

პასუხი AI-სგან

დაცული არ არის პირდაპირ შედარება ოპერატორით ==, რადგან წარმოდგენის და რაუნდინგის სპეციფიკების გამო. ამის ნაცვლად, უნდა შემოწმდეს, არის თუ არა მნიშვნელობათა სხვაობის აბსოლუტური მნიშვნელობა მცირე ზღვარის (epsilon) ფარგლებში.

bool are_equal(float a, float b, float epsilon = 0.00001f) {
    return std::abs(a - b) < epsilon;
}

მრეწველად უფრო სტაბილური მიდგომა ითვალისწინებს ურთიერთმნიშვნელოვან შეცდომას, განსაკუთრებით როდესაც შედარება ხორციელდება ძალიან დიდ ან ძალიან პატარა რიცხვებზე:

#include <cmath>
#include <limits>

bool are_equal_robust(float a, float b, float epsilon = std::numeric_limits<float>::epsilon()) {
    // შედარება განსხვავების ზომის გათვალისწინებით
    // მნიშვნელოვანია, რომ ცალკე განიხილოს ნული და უსასრულო შემთხვევები
    if (a == b) {
        return true; // მოიცავს შემთხვევებს, სადაც a=b (შეიცავს უსასრულო და NaN, თუ ისინი თანხვედრაში არიან – რაც NaN-ისთვის არ არის, მაგრამ უსასრულოსთვის არის)
    }

    float absolute_difference = std::abs(a - b);
    float max_abs = std::max(std::abs(a), std::abs(b));

    if (max_abs < epsilon) {
        return absolute_difference < epsilon; // ორივე რიცხვი ახლოს არის ნულთან
    } else {
        return absolute_difference / max_abs < epsilon; // ურთიერთმნიშვნელოვანი განსხვავების შედარება
    }
}

epsilon არჩევანი დამოკიდებულია საჭირო სიზუსტეზე და შედარების მნიშვნელობების დიაპაზონზე. std::numeric_limits<float>::epsilon() წარმოადგენს ყველაზე მცირე რიცხვს, რომლისთვისაც შესრულდება 1.0 + epsilon განსხვავება 1.0-დან.

მნიშვნელოვანია გახსოვდეთ, რომ NaN (Number არა) თანმიმდევრულად ყოველთვის false-ს აბრუნებს, მათ შორის nan == nan. თუ საჭიროა NaN-ის დამუშავება, ეს უნდა გაკეთდეს ცალკე.