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-ի հետ համեմատությունը միշտ false է, ներառյալ nan == nan։ Եթե անհրաժեշտ է NaN-ների հատուկ մշակում, դա պետք է առանձին անել։