Como calcular a raiz quadrada de um número em python

Introdução

o raiz quadrada de um número é uma função matemática muito comum usada em todos os aspectos da ciência – física, matemática, ciência da computação, etc. – modelando o que podemos observar com cálculo.

Neste artigo, vamos dar uma olhada várias maneiras de calcular a raiz quadrada de um número em Python. Por fim, faremos um Referência de desempenho com números constantes e aleatórios, bem como listas de números aleatórios para testar todas as abordagens.

Calcular raiz quadrada em Python com NumPy

NumPy é uma biblioteca de computação científica, que se viu presente em muitos aplicações e casos de uso. Naturalmente, tem muitos wrappers de funções matemáticas como métodos auxiliares.

Se ainda não estiver instalado, você pode instalá-lo via pip:

$ pip install numpy

Em termos de NumPy, o sqrt() calcula a raiz quadrada de um número e retorna o resultado:

import numpy as np x = np.sqrt(2) print(x)

Isto resulta em:

1.4142135623730951

Além de usar uma única variável como argumento, sqrt() também é capaz de analisar listas e retornar uma lista de raízes quadradas:

arr = [2, 3, 5, 7] roots = np.sqrt(arr) print(roots)

Isto resulta em:

[1.41421356 1.73205081 2.23606798 2.64575131]

o sqrt() tem uma limitação – não pode calcular uma raiz quadrada de um número negativo, porque a operação de raiz quadrada com números reais só é definida para números positivos.

Tentando inserir -4 no sqrt() resultará em uma exceção:

print(np.sqrt(-4))

Tentar calcular a raiz quadrada de um número negativo resultará em um aviso e um nan:

RuntimeWarning: invalid value encountered in sqrt nan

Calcular raiz quadrada de número complexo com Numpy

Felizmente, o NumPy não está restrito a trabalhar apenas com números reais – ele também pode funcionar com números complexos:

import numpy as np complex_number = -1 + 1j complex_array = [-2, 3, complex_number] complex_root = np.sqrt(complex_number) complex_array_roots = np.sqrt(complex_array) print(f"Square root of '{complex_number}':n {complex_root}") print(f"Square roots of '{complex_array}':n {complex_array_roots}")

Se houver pelo menos 1 número complexo em uma lista, todos os números serão convertidos e tratados como complexos, portanto, mesmo inteiros negativos podem ser adicionados:

Square root of '(-1+1j)': (0.45508986056222733+1.09868411346781j) Square roots of '[-2, 3, (-1+1j)]': [0. +1.41421356j 1.73205081+0.j 0.45508986+1.09868411j]

do Python matemática Módulo

o math é um módulo padrão empacotado com Python. Está sempre disponível, mas precisa ser importado e fornece wrappers para algumas funções comuns, como raiz quadrada, potências, etc:

import math
math.sqrt()

o sqrt() do math é uma função direta que retorna a raiz quadrada de qualquer número positivo:

print(math.sqrt(2))

Isto resulta em:

1.4142135623730951

Ao contrário do NumPy sqrt()ele só pode funcionar em um único elemento, então se você quiser calcular a raiz quadrada de todos os elementos em uma lista, você terá que usar um for loop ou uma compreensão de lista:

import math arr = [2, 3, 5, 7] roots = [] for x in arr: roots.append(math.sqrt(x)) # OR roots = [math.sqrt(x) for x in arr]

Em ambos os casos, o roots conterá:

[1.4142135623730951, 1.7320508075688772, 2.23606797749979, 2.6457513110645907]
math.pow()

A raiz quadrada de um número também pode ser calculada elevando um número a uma potência de ½:

$$sqrt x = x^{frac 1 2}

$$

Então, na verdade, encontrar a raiz quadrada de um número pode ser expresso como elevar o número a uma potência de ½. math.pow() recebe dois argumentos – a base e o expoente, e eleva a base à potência de um expoente:

print(math.pow(2, 0.5))

Naturalmente, isso resulta em:

1.4142135623730951

o ** Operador

o ** operador é um operador binário, o que significa que funciona com dois valores, assim como a multiplicação regular com * faz. No entanto, como é um operador usado para exponenciação, elevamos seu argumento esquerdo à potência de seu argumento direito.

Essa abordagem pode ser usada da mesma forma que a anterior:

print(2 ** 0.5)

E também resulta em:

1.4142135623730951

o Pancada() Função

Python tem outro, embutido pow() método que não requer uma importação do math. Este método é tecnicamente diferente do math.pow() método internamente.

math.pow() lança elementos implicitamente para duplosenquanto pow() usa a implementação interna do objeto, baseada na ** operador. Embora essa diferença na implementação possa justificar o uso de um ou outro em determinados contextos, se você estiver apenas calculando a raiz quadrada de um número, não verá a diferença:

print(pow(2, 0.5))

Isto resulta em:

1.4142135623730951

Referência de desempenho

Então, qual produz o melhor desempenho e qual você deve escolher? Como de costume, não há um corte claro vencedor, e depende sobre o uso dos métodos. Ou seja, se você estiver trabalhando com números constantes, números aleatórios ou uma matriz de números aleatórios em uma escala maior – esses métodos terão um desempenho diferente.

Vamos testá-los todos em números constantes, números aleatórios e matrizes de números aleatórios:

import timeit print("Time to execute 100k operations on constant number: n") print("math.sqrt(): %ss" % timeit.timeit("math.sqrt(100)", setup="import math", number=100000)) print("math.pow(): %ss" % timeit.timeit("math.pow(100, 0.5)", setup="import math", number=100000)) print("pow(): %ss" % timeit.timeit("pow(100, 0.5)", number=100000)) print("np.sqrt(): %ss" % timeit.timeit("np.sqrt(100)", setup="import numpy as np", number=100000)) print("** operator: %ss" % timeit.timeit("100 ** 0.5", number=100000)) print("nTime to execute 100k operations on random number: n") print("math.sqrt() %ss" % timeit.timeit("math.sqrt(random.random())", setup="import math; import random;", number=100000)) print("math.pow(): %ss" % timeit.timeit("math.pow(random.random(), 0.5)", setup="import math; import random", number=100000)) print("pow(): %ss" % timeit.timeit("pow(random.random(), 0.5)", setup="import random", number=100000)) print("np.sqrt(): %ss" % timeit.timeit("np.sqrt(random.random())", setup="import numpy as np; import random", number=100000)) print("** operator: %ss" % timeit.timeit("random.random() ** 0.5", setup="import random", number=100000)) print("nTime to execute 100k operations on list of random numbers: n") print("math.sqrt() %ss" % timeit.timeit("[math.sqrt(x) for x in np.random.rand(100)]", setup="import math; import numpy as np;", number=100000)) print("math.pow(): %ss" % timeit.timeit("[math.pow(x, 0.5) for x in np.random.rand(100)]", setup="import math; import numpy as np;", number=100000)) print("pow(): %ss" % timeit.timeit("[pow(x, 0.5) for x in np.random.rand(100)]", setup="import numpy as np;", number=100000)) print("np.sqrt(): %ss" % timeit.timeit("np.sqrt(np.random.rand(100))", setup="import numpy as np; import numpy as np;", number=100000)) print("** operator: %ss" % timeit.timeit("np.random.rand(100) ** 0.5", setup="import numpy as np", number=100000))

Passamos todos os métodos descritos acima pelo mesmo teste – um número constante (que provavelmente será armazenado em cache para otimização), um número aleatório em cada uma das 100 mil iterações e um Lista de 100 números aleatórios.

Como calcular a raiz quadrada de um número em python

Observação: Apenas os números relativos em cada teste em comparação com outros métodos nesse teste são relevantes, pois leva mais tempo para gerar 100 números aleatórios do que usar o valor constante (em cache).

A execução deste trecho de código resulta em:

Time to execute 100k operations on constant number: math.sqrt(): 0.014326499999999999s math.pow(): 0.0165132s pow(): 0.018766599999999994s np.sqrt(): 0.10575379999999998s ** operator: 0.0006493000000000193s Time to execute 100k operations on random number: math.sqrt() 0.019939999999999958s math.pow(): 0.022284300000000035s pow(): 0.0231711s np.sqrt(): 0.09066460000000004s ** operator: 0.018928s Time to execute 100k operations on list of random numbers: math.sqrt() 2.7786073s math.pow(): 2.9986906s pow(): 3.5157339999999992s np.sqrt(): 0.2291957s ** operator: 0.2376024000000001s

Com números constantes – o math.pow(), math.sqrt() e pow()s superam significativamente o NumPy sqrt()pois eles podem utilizar melhor o cache na CPU no nível do idioma.

Com números aleatórios, o cache não funciona também e vemos discrepâncias menores.

Com listas de números aleatórios, np.sqrt() supera todos os três métodos integrados significativamentee as ** operador atua no mesmo estádio.

Para resumir:

  • Por constant numbersa ** operador clearly tem o melhor desempenho na máquina de teste, executando 16 vezes mais rápido que os métodos integrados.
  • Por random numbers, np.sqrt() supera os métodos embutidos, e o ** operador, no entanto, não há discrepância significativa nos resultados.
  • Por random arraysa np.sqrt() supera os métodos internos, mas o ** operador está muito próximo.

Dependendo da entrada concreta com a qual você está lidando – você escolherá entre essas funções. Embora possa parecer que eles vão tudo tenha um bom desempenho, e enquanto estiver em a maioria casos, não fará muita diferença, ao lidar com grandes conjuntos de dados, até mesmo uma redução de 10% no tempo de processamento pode ajudar a longo prazo.

Dependendo dos dados que você está processando – test the different approaches on your local machine.

Conclusão

Neste pequeno artigo, examinamos várias maneiras de calcular o Raiz quadrada de um número em Python.

Demos uma olhada no mathde pow() e sqrt()s, bem como o built-in pow()NumPy’s sqrt() e a ** operador. Por fim, comparamos os métodos para comparar seu desempenho em diferentes tipos de entrada – números constantes, números aleatórios e listas de números aleatórios.