In primo luogo, a patto di avere un operatore di logaritmo specifico (molti linguaggi forniscono logaritmi per basare 10
o base e
solo), logab
può essere calcolato come logxb/logxa
(dove x
è ovviamente una base fornita dalla lingua dell'utente).
Python va meglio perché può elaborare il logaritmo di una base arbitraria arbitraria senza quella complicata uguaglianza di cui sopra.
Quindi in un modo o nell'altro, è possibile ottenere il logaritmo su una base specifica. Da lì, se il registro di b
nella base a
è un numero intero (nota 1), quindi è una potenza di a
.
Così mi piacerebbe iniziare con il seguente codice, ora con il rilevamento dei bordi e minuscole aggiunto:
# Don't even think about using this for negative powers :-)
def isPower (num, base):
if base == 1 and num != 1: return False
if base == 1 and num == 1: return True
if base == 0 and num != 1: return False
power = int (math.log (num, base) + 0.5)
return base ** power == num
Si veda ad esempio il seguente programma completo che mostra in azione:
import math
def isPower (num, base):
if base == 1 and num != 1: return False
if base == 1 and num == 1: return True
if base == 0 and num != 1: return False
power = int (math.log (num, base) + 0.5)
return base ** power == num
print isPower (127,2) # false
print isPower (128,2) # true
print isPower (129,2) # false
print
print isPower (26,3) # false
print isPower (27,3) # true
print isPower (28,3) # false
print isPower (3**10,3) # true
print isPower (3**129,3) # true
print
print isPower (5,5) # true
print isPower (1,1) # true
print isPower (10,1) # false
Se sei il tipo che è preoccupato per le operazioni in virgola mobile, puoi fare farlo con ripetute moltiplicazioni ma dovresti testare la performa nce di una soluzione del genere poiché è probabile che il software sia notevolmente più lento di quanto non lo sia nell'hardware. Ciò non importa molto per cose come isPower(128,2)
ma potrebbe diventare una preoccupazione per isPower(verybignum,2)
.
Per una variante punto non fluttuante del codice di cui sopra:
def isPower (num, base):
if base == 1 and num != 1: return False
if base == 1 and num == 1: return True
if base == 0 and num != 1: return False
testnum = base
while testnum < num:
testnum = testnum * base
return testnum == num
Ma assicurarsi che sia testato contro la vostra più grande numero e la base più piccola per essere sicuri di non avere eventuali shock prestazioni.
(Nota 1) tenere a mente la possibilità che in virgola mobile imprecisione può significare che non è esattamente un numero intero. Potrebbe essere necessario utilizzare un confronto "abbastanza vicino".
Non dovresti controllare se il math.log (n, base) è * qualsiasi * intero? –
Perché 'math.log (n, base)' mai uguale 'base ** n'? 128 è una potenza di 2, ma '2 ** 128' non è sicuramente' 7'. – chrisaycock