- PVSM.RU - https://www.pvsm.ru -

Всем нолям ноль: почти все языки программирования делают это

Решил я намедни сделать для себя небольшой, но очень удобный велосипед для вычисления всяких полезных математических функций. Стоит отметить, что пишу я на разных языках, и в этот раз выбор пал на 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")

И этот змей выдает единицу и никаких ошибок. Да что ж такое-то?! Полез в эти ваши интернеты и наткнулся на вот такой список [1]. Вот ведь подсуропили нам ребятки — почти во всех языках выдается единица, вместо ожидаемой ошибки, как, например, при делении на ноль.

И такое встречается в браузерных калькуляторах той же корпорации добра, яндекса, стандартных системных. И это, по моему скромному мнению, чертовски серьезная ошибка. Поэтому, не удивляйтесь, когда увидите в коде:

T correct_pow(T a, T b) {
    if(a == 0 && b == 0) {
        throw std::
    }

    return(pow(a, b));

Автор: NTP

Источник [2]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/114592

Ссылки в тексте:

[1] список: http://rosettacode.org/wiki/Zero_to_the_zero_power

[2] Источник: https://habrahabr.ru/post/278971/