Решил я намедни сделать для себя небольшой, но очень удобный велосипед для вычисления всяких полезных математических функций. Стоит отметить, что пишу я на разных языках, и в этот раз выбор пал на C++. Пилю я, значит, сей чудесный трехколесный транспорт и параллельно занимаюсь юнит-тестированием свежесозданных функций… И тут нате-здрасте — один из тестов выдает мне совсем не тот результат, которого я ждал. Готовы?!
Ноль в степени ноль равен единице!!! (многозначительный трагический взгляд)
Ну, думаю, бывает всякое и разное. Решил проверить функцию pow() отдельно, наивно полагая, что словлю хотя бы исключение:
#include <cmath>
#include <iostream>
#include <stdexcept>
int main(void) {
try {
std::cout << "zero at degree zero: " << std::pow(0, 0) << std::endl;
}
catch(std::exception &ex) {
std::cerr << ex.what() << std::endl;
}
return 0;
}
Ожидания подтвердились — никаких исключений (все в полном соответствии с документацией), результат в консоли — упорная единица.
Позволю себе небольшое отступление на минутку науки. Если совсем коротко и упрощенно, то:
Возведение в степень — бинарная операция, при которой число a умножается само на себя столько раз, сколько указано в показателе степени b. Записывается это как ab и читается "a в степени b". Например:
35 = 3*3*3*3*3 или 52 = 5*5
Но как быть, если показатель степени равен нулю? Как должна выглядеть запись после знака равенства?.. Решение оказалось довольно простым — в силу свойств степени, число ab можно представить в виде ab = ac * a(b-c). Для наглядности:
47 = (4*4*4)*(4*4*4*4) = 43 * 44
Число же в нулевой степени можно представить как a0 = ab * a-b. Но что это за отрицательная степень такая, как понимать? Ответ довольно прост: действие, обратное умножению — деление. Так, число в отрицательной степени означает единицу, деленную на число в положительной степени — a-b = 1/ab.
Исходя из вышенаписанного, мы можем сделать довольно простой вывод:
a0 = ab * a-b = ab/ab = 1
Но как быть в случае, если a = 0? Возникает довольно неприятная ситуация — деление нуля на ноль, на который делить строго запрещено под страхом возникновения сверхмассивных черных дыр.
Есть и другие способы вычисления нуля в нулевой степени и одни дают единицу, другие ноль, третьи опять деление на ноль. Такая ситуация, когда что-то не поддается вычислению, в математике называется неопределенностью (нельзя определить однозначно).
Ну вот, кратенький ликбез закончен.
Теперь вернемся снова к программированию… Решил я проверить как дела обстоят в других языках и запустил Python:
import math
try:
print("0**0:", 0**0)
print("pow(0, 0)", math.pow(0, 0))
except:
print("Exception")
И этот змей выдает единицу и никаких ошибок. Да что ж такое-то?! Полез в эти ваши интернеты и наткнулся на вот такой список. Вот ведь подсуропили нам ребятки — почти во всех языках выдается единица, вместо ожидаемой ошибки, как, например, при делении на ноль.
И такое встречается в браузерных калькуляторах той же корпорации добра, яндекса, стандартных системных. И это, по моему скромному мнению, чертовски серьезная ошибка. Поэтому, не удивляйтесь, когда увидите в коде:
T correct_pow(T a, T b) {
if(a == 0 && b == 0) {
throw std::
}
return(pow(a, b));
Автор: NTP
Не удивлён, что выдаёт 1, так как прекрасно помню ещё со школы, как звучит правило.
Любое число в степени 0, равно 1.