Попался на глаза пример шаблонного кода на C++
template <typename T>
T tmax(T a, T b) {
return b < a ? a : b;
}
Я сразу заметил неточность, которая возникнет при использовании дробных чисел
tmax(0.0f, NAN) | = | NAN | ||
tmax(NAN, 0.0f) | = | 0.0f |
По природе неопределённости функция, возвращающая максимальное из двух значений, в обоих случаях должна была бы давать неопределённость. Это может показаться несущественным, но всё это играет большую роль, когда речь заходит о максимальной корректности.
В стандартной библиотеке уже есть воплощение функции max, но неточность с дробями оказалась и в ней
std::max(0.0f, NAN) | = | 0.0f | ||
std::max(NAN, 0.0f) | = | NAN |
Противоположность закономерна и объясняется противоположным расположением операндов.
О том, что это некорректность, а не так и задумано, можно убедиться взглянув на результат специализированной функции.
fmaxf(0.0f, NAN) | = | 0.0f | ||
fmaxf(NAN, 0.0f) | = | 0.0f |
Не обошлось без сюрпризов и здесь. Равенство 0 объясняется тем, что NAN трактуется авторами не как неопределённость, а как отсутствие данных, что довольно странно, ведь NAN образуется в операциях, в которых именно создаётся неопределённое число, а не устраняется. Но результат хотя бы одинаковый в обоих случаях, что всё равно лучше шаблонной функции, нарушающей ещё и коммутативность.
Самый правильный результат для float выдаёт такая функция
float mxf(float a, float b) {
if (a < b || b != b) {
a = b;
}
return a;
}
mxf(0.0f, NAN) | = | NAN | ||
mxf(NAN, 0.0f) | = | NAN |
Комментариев нет:
Отправить комментарий