2015-12-31 5 views
1

Мне нужно решить для любого корня степени n, что он имеет целочисленный корень. Моя первоначальная идея заключалась в том, чтобы найти приблизительный корень, используя метод Ньютона, однако, будет ли функция мощности не давать нам максимальной точности, которая может быть выражена поплавками машины?Как решить, если целое число имеет целочисленный корень?

function hasIntegerRoot($integer, $degree) { 
    if($degree == 0 || $degree == 1) return true; 

    $r = pow($integer, 1/$degree); 

    //get nearest integer 
    $n = round($r); 

    //solve n^x 
    $answer = pow($n, $degree); 

    return $answer == $integer; 
} 

У меня есть два вопроса:

функция мощности Помогла ли достаточно близко к целому корню так, что округление поплавка никогда не возвращает неправильный целый корень? Это потребовало бы, чтобы он был выключен на 0,5, что интуитивно я не мог себе представить, но у меня нет никаких трудных доказательств.

Во-вторых, имеет ли инструкция return десятичная математика? Проблема в том, что для достаточно больших $ integer и $ n PHP будет использовать float. Это желательно, поскольку он не будет переполнять большие целые числа; однако он оставляет использование математики с плавающей запятой, которая по своей сути имеет неточности. Могут ли эти неточности повлиять на мой алгоритм?

Опять же, интуитивно я чувствую, что ограничения на то, что $ integer является целым числом и что корень $ n должен быть целым, избегает любых математических проблем с плавающей запятой. В математике никогда не было бы десятичных знаков. Однако я не могу полностью доказать интуицию.

+0

Тот факт, что вы используете 'pow()' и reciprocals означает, что вы включаете поплавки. –

+0

Вы можете использовать BC Math fucntions, который поддерживает числа любого размера и точности **, но ** представлены в виде строк –

ответ

0

Я не полагаюсь на pow(), будучи достаточно точным для этого, но вы можете начать с pow (..., 1/degree), а затем пройти $ n вверх или вниз до $ n ** $ degree соответствует или пересекает $ integer. (Но реализовать ** степени самостоятельно, так как внутренне он использует Pow())

пау() является приближенным, что не всегда возвращает наиболее возможное значение для точного результата