Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Biblioteca de testes de conceito de algoritmos de funções úteis para matemática financeira em linguagens que só tenham inteiros.
- O fato de ser em Python é para testes dos resultados sem a dificuldade de ser implementada em uma linguagem real.
- A solução que é o "domínio do problema" resolve cálculos entre juros e acréscimos, normalmente 0%-10% de juros até 120 parcelas.
- Funções que trabalham com logaritmos e exponenciação de fixed-points só são garantidamente precisas dentro desse domínio.
- Não se tentou competir com bibliotecas matemáticas prontas, que podem fazer os mesmos cálculos em domínios mais amplos,
- ela somente demonstra que, mesmo sem suporte a ponto flutuante (ou fixo) em uma linguagem, ainda se pode implementar matemática
- de forma portável, nesse caso, usando séries de Taylor que são precisas especificamente para um problema de matemática financeira.
- """
- # variáveis gerais para fixed-point com 35 dígitos, com escala computada,
- # totais de iterações para lnfp() e expfp(), número UM e INFINITO (para legibilidade)
- # TOTLN e TOTEXP são superdimensionados para garantir convergência no domínio do problema
- DIGITOS = 35
- ESCALA = 10 ** DIGITOS
- TOTLN = 2 * DIGITOS
- TOTEXP = 3 * DIGITOS
- UM = ESCALA
- INFINITO = ESCALA * ESCALA # aqui deve ser definido um número fora do domínio do problema, por ser impossível na prática
- # ele é retornado por divfp quando dá divisão por zero, para ser tratado
- # soma e subtração não mudam escala; usar + e - direto é mais claro; mas nada impede usar para manter o estilo
- #
- # def addfp(a, b):
- # """operação + de dois fixed-points"""
- # return a + b
- #
- # def subfp(a, b):
- # """operação - de dois fixed-points"""
- # return a - b
- def mulfp(a, b):
- """operação * de dois fixed-points"""
- if a * b < 0:
- return (a * b - ESCALA // 2) // ESCALA
- else:
- return (a * b + ESCALA // 2) // ESCALA
- def divfp(a, b):
- """operação / de dois fixed-points"""
- if b == 0:
- return INFINITO # divisão por zero retorna valor fora do domínio do problema (ou não trate aqui, se preferir)
- if (a < 0) ^ (b < 0):
- return (a * ESCALA - b // 2) // b
- else:
- return (a * ESCALA + b // 2) // b
- def inttofp(x):
- """torna um integer em fixed-point com DIGITOS de dígitos (usando ESCALA que já está computada)"""
- return x * ESCALA
- def lnfp(x):
- """logaritmo natural de um fixed-point; o domínio do problema dessa função é x entre 1.0 e 1.1 (para matemática financeira)"""
- termo = divfp(x - UM, x + UM)
- yy = mulfp(termo, termo)
- soma = 0
- for indice in range(TOTLN):
- soma = soma + divfp(termo, inttofp(2 * (indice + 1) - 1))
- termo = mulfp(termo, yy)
- return 2 * soma
- def expfp(x):
- """número de Euler elevado a um fixed-point; o domínio do problema dessa função é x entre 0.0 e 6.0 (para matemática financeira)"""
- termo = UM
- soma = UM
- for indice in range(TOTEXP):
- termo = mulfp(termo, divfp(x, inttofp(indice + 1)))
- soma = soma + termo
- return soma
- def powfp(base, expoente):
- """base fixed-point elevada a expoente a fixed-points, essa função tem a precisão de acordo com lnfp() e expfp()
- o domínio do problema dessa função é base entre 1.0 e 1.1 e expoente entre 0 e 120"""
- return expfp(mulfp(expoente, lnfp(base)))
- def powintfprec(base, expoente):
- """base fixed-point elevada a expoente integer, recursiva, para máxima precisão, expoente pode ser negativo"""
- if expoente < 0:
- return powintfprec(divfp(UM, base), -expoente)
- if expoente == 0:
- return UM
- if expoente % 2 == 0:
- return powintfprec(mulfp(base, base), expoente // 2)
- return mulfp(base, powintfprec(mulfp(base, base), (expoente - 1) // 2))
- def powintfpfor(base, expoente):
- """base fixed-point elevada a expoente integer, iterativa, para máxima precisão, expoente pode ser negativo"""
- if expoente < 0:
- base = divfp(UM, base)
- expoente = -expoente
- if expoente == 0:
- return UM
- produto = UM
- for indice in range(expoente):
- produto = mulfp(produto, base)
- return produto
- def powintrec(base, expoente):
- """base integer elevada a expoente integer, recursiva; o domínio da função é fazer 10 ** DIGITOS em linguagens sem **; não aceita expoente negativo"""
- if expoente < 0:
- return 0
- if expoente == 0:
- return 1
- if expoente % 2 == 0:
- return powintrec(base * base, expoente // 2)
- return base * powintrec(base * base, (expoente - 1) // 2)
- def powintfor(base, expoente):
- """base integer elevada a expoente integer, iterativa; o domínio da função é fazer 10 ** DIGITOS em linguagens sem **; não aceita expoente negativo"""
- if expoente < 0:
- return 0
- if expoente == 0:
- return 1
- produto = 1
- for indice in range(expoente):
- produto = produto * base
- return produto
- def strfp(x):
- """função para converter o número fixed-poin em string com ponto decimal"""
- sign = "-" if x < 0 else ""
- x = abs(x)
- inteiro = x // ESCALA
- frac = x % ESCALA
- frac_str = str(frac).rjust(DIGITOS, "0")
- # remove zeros à direita (opcional, mas prático)
- frac_str = frac_str.rstrip("0")
- if frac_str == "":
- return f"{sign}{inteiro}"
- else:
- return f"{sign}{inteiro}.{frac_str}"
- ################################################## TESTES ##################################################
- num1 = inttofp(2)
- num2 = inttofp(3)
- num3 = divfp(num1, num2)
- print("div = " + strfp(num3))
- num3 = mulfp(num1, num2)
- print("mul = " + strfp(num3))
- print("ln = " + strfp(lnfp(num1)))
- print("exp = " + strfp(expfp(num1)))
- base = inttofp(103) // 100 # número 1.03
- expoente = inttofp(5) // 10 # número 0.5
- print("pow = " + strfp(powfp(base, expoente)))
- minDiferenca = inttofp(1) // 10 # número 0.1
- precisao = 15
- print("powintfprec = " + strfp(powintfprec(minDiferenca, precisao)))
- print("powintfpfor = " + strfp(powintfpfor(minDiferenca, precisao)))
- print("powintrec = " + str(powintrec(10, DIGITOS)))
- print("powintfor = " + str(powintfor(10, DIGITOS)))
- """ RETORNOS DOS TESTES PARA VALIDAÇÃO
- div = 0.66666666666666666666666666666666667
- mul = 6
- ln = 0.69314718055994530941723212145817658
- exp = 7.38905609893065022723042746057500784
- pow = 1.01488915650922194686485201189358745
- powintfprec = 0.000000000000001
- powintfpfor = 0.000000000000001
- powintrec = 100000000000000000000000000000000000
- powintfor = 100000000000000000000000000000000000
- """
Add Comment
Please, Sign In to add comment