Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Como fazer uma classe Python para modelar uma função de segundo grau?

0 votos
23 visitas
perguntada Set 26 em Ciência da Computação por bonfim_tiago (6 pontos)  

Exercício 7.7 do livro "A Primer on Scientific Programming", Página 399.

Compartilhe

1 Resposta

0 votos
respondida Set 26 por bonfim_tiago (6 pontos)  

Boa tarde a todos!

O exercício de hoje solicita que seja modelada uma classe para para implementar uma função de segundo grau (quadrática). De forma genérica, pretende-se modelar a função f(x; a, b, c) = ax2 + bx + c.

Tendo em vista que a teoria matemática envolvida na resolução desse exercício é trivial, vamos partir diretamente para o código de implementação da classe, que segue abaixo:

class Quadratic():
    # Classe Quadratic responsável pela modelagem de um polinômio genérico de 
    # segundo grau f(x; a, b, c) = ax2 + bx + c., com parâmetros 
    # a: coeficiente multiplicativo do termo quadrático
    # b: coeficiente multiplicativo do termo linear
    # c: coeficiente escalar (offset)

    def __init__(self, a:float, b:float, c:float):
        self.a = a
        self.b = b
        self.c = c

O construtor da função basicamente recebe as três variáveis que definem a função e os atribuem para os parâmetros da instância da classe, conforme segue apresentado.

Nesse ponto, destaca-se que o exercício solicitava a implementação de três funcionalidades nessa classe, sendo eles:

  1. Uma função que possa calcular o valor de f num ponto x específico;
  2. Uma função que retorne uma tabela com os valores de domínio e imagem da função f compreendidos em um intervalo [L, R];
  3. Uma função capaz de calcular as raízes da função.

Assim, essas três funcionalidades foram implementadas utilizando-se três métodos distintos. A implementação do primeiro deles segue apresentada abaixo:

def function_evaluate(self, x:float):
   # função que retorna a imagem f(x) do objeto para o valor x informado
   return self.a*x*x + self.b*x + self.c

Esse método é basicamente autoexplicativo e simplesmente retorna o resultado da operação algébrica implementada de forma a se calcular o valor f(x) da função.

A segunda função é ligeiramente mais interessante e segue apresentada abaixo:

 def function_interval_evaluate(self, lower_threshold:int, upper_threshold:int):
        # função que retorna uma lista de tuplas contendo o par (domínimo, imagem) para elementos no intervalo [lower_threshold, upper_threshold]
        table_values = []
        for step in range(lower_threshold, upper_threshold+1):
            table_values.append((step, self.a*step*step + 
            self.b*step + self.c))
        return table_values

Ela faz uso de algumas funcionalidades ligeiramente mais sofisticadas do Python, como seria o caso do range, capaz de gerar um intervalo de inteiros dentro do intervalo de interesse, nesse caso, [lowerthreshold, upperthreshold]. Dentro desse laço for, basicamente se calcula o valor da função no ponto x novamente. Detalhe relevante aqui é o fato de que poderíamos simplesmente chamar a primeira função no interior desse for para a realização desse cálculo. Apesar de conceitualmente mais elegante e modularizada a solução; no caso concreto, vislumbro pouco ganho de desempenho, de forma que procedi com a implementação direta da função, tendo em vista se tratar meramente de uma linha de código. De toda sorte, fica aí o registro.

Por fim, segue a implementação da última funcionalidade solicitada, no método da classe apresentado abaixo:

 def function_roots_eval(self):
        delta = self.b*self.b - 4*self.a*self.c
        roots = {'root1': (-self.b + (delta)**1/2)/2*self.a,
            'root2': (-self.b - (delta)**1/2)/2*self.a
        } 
        return roots

Em que consta basicamente a implementação da equação de Bhaskara para resolução do problema.

Segue, então, o código capaz de testar a classe implementada:

# Bloco de testes
poly1 = Quadratic(1, -4, 4)
print("1º Teste - Valor da função no ponto x = 2:", poly1.function_evaluate(2))
print("2º Teste - Raízes do polinômio informado: ", poly1.function_roots_eval())
print("3º Teste - Tuplas(domínio, imagem) do polinômio informado no intervalo compreendido [0:50]:")
print(poly1.function_interval_evaluate(0,50))

Juntamente com os resultados da compilação:

1º Teste - Valor da função no ponto x = 2: 0
2º Teste - Raízes do polinômio informado: {'root1': 2.0, 'root2': 2.0}
3º Teste - Tuplas(domínio, imagem) do polinômio informado no intervalo compreendido [0:50]:
[(0, 4), (1, 1), (2, 0), (3, 1), (4, 4), (5, 9), (6, 16), (7, 25), (8, 36), (9, 49), (10, 64), (11, 81), (12, 100), (13, 121), (14, 144), (15, 169), (16, 196), (17, 225), (18, 256), (19, 289), (20, 324), (21, 361), (22, 400), (23, 441), (24, 484), (25, 529), (26, 576), (27, 625), (28, 676), (29, 729), (30, 784), (31, 841), (32, 900), (33, 961), (34, 1024), (35, 1089), (36, 1156), (37, 1225), (38, 1296), (39, 1369), (40, 1444), (41, 1521), (42, 1600), (43, 1681), (44, 1764), (45, 1849), (46, 1936), (47, 2025), (48, 2116), (49, 2209), (50, 2304)]

Comentário relevante para o resultado do 3º teste, que contém os valores de domínio-imagem inseridos em tuplas e, posteriormente, adicionados em uma lista dentro do intervalo fornecido [0, 50]. De fato, a forma como o Python estrutura seus dados beira o inacreditável. Muito interessante que uma lista possa conter outros tipos complexos de estruturas de dados.

Pessoal, a implementação solicitada, acredito eu, que seja essa.

Fico no aguardo pelos comentários do aluno revisor, bem como por quaisquer outros comentários que possam ser feitos e que serão muito bem-vindos.

Abraços a todos!

...