• Nenhum resultado encontrado

Commons Math é uma biblioteca desenvolvida em JAVA composta de um pequeno conjunto de utilitários com objetivo de resolver alguns problemas de programação, como os citados abaixo:

• Variâncias e estatísticas de resumo para uma lista de números;

• Ajuste de uma reta a um conjunto de pontos por meio de regressão linear;

• Encontrar uma curva suave que passe através de uma coleção de pontos (interpola- ção);

• Colocação de um modelo paramétrico para um conjunto de medidas usando méto- dos de mínimos quadrados;

• Resolução de equações envolvendo funções reais • Resolução de sistemas de equações lineares; • Solução de equações diferenciais ordinárias; • Minimização de funções multi-dimensional;

• Geração de números aleatórios com mais restrições (por exemplo, a distribuição gama), do que é possível usar no JDK;

• Realização de testes de significância estatística;

• Diversas funções matemáticas tais como fatoriais, coeficientes binomial e "funções especiais".

3.8.1

Organização

Commons Math é dividido em catorze sub-pacotes, com base na funcionalidade for- necida. Estes sub-pacotes são:

1. org.apache.commons.math.stat - estatísticas, testes estatísticos.

2. org.apache.commons.math.analysis - integração, interpolação, polinômios. 3. org.apache.commons.math.random - números aleatórios, cordas e de geração de dados.

4. org.apache.commons.math.special - funções especiais (Gama, Beta).

5. org.apache.commons.math.linear - matrizes, resolução de sistemas lineares.

6. org.apache.commons.math.util - matemática comum/ funções estendendo java.lang.Math. 7. org.apache.commons.math.complex - números complexos.

8. org.apache.commons.math.distribution - distribuições de probabilidade. 9. org.apache.commons.math.fraction - números racionais.

10. org.apache.commons.math.transform - métodos de transformação (Fast Fou- rier).

11. org.apache.commons.math.geometry - geometria (espaços euclidianos e Parti- cionamento Espacial Binária).

12. org.apache.commons.math.optimization - maximização ou minimização da função.

13. org.apache.commons.math.ode - equações diferenciais ordinárias integração. 14. org.apache.commons.math.genetics - algoritmos genéticos.

3.8.2

Números Complexos

O pacote org.apache.commons.math.complex é responsável pela criação do tipo nú- mero complexo e pela implementação das suas funções.

Este pacote é composto pelas seguintes classes: Complex

Esta classe é responsável pela representação do número complexo, ou seja, um nú- mero com uma parte real e uma parte imaginária.

As implementações de operações aritméticas lidam com NaN e valores infinitos de acordo com as regras para o tipo Double, ou seja, equals (java.lang.Object) é uma relação de equivalência para todas as instâncias que têm um NaN, na parte real ou imaginária, por exemplo, são considerados iguais:

• 1 + NaNi • NaN + i • NaN + NaNi Construtores:

1. Complex(double real): Cria um número complexo dado sua parte real.

2. Complex(double real, double imaginaria): Cria um número complexo dado sua parte real e imaginária.

Métodos:

A Tabela 3.4 apresenta todos os métodos implementados na classe Complex: Tabela 3.4: Métodos da classe Complex

Método Função

abs() Retorna o valor absoluto de um número com- plexo

acos() Calcula o arco-cosseno de um número com- plexo

add(Complex c) Retorna o complexo cujo valor é (this + c) add(double d) Retorna o complexo cujo valor é (this + d) asin() Calcula o arco-seno de um número complexo atan() Calcula o arco-tangente de um número com-

plexo

cosh() Calcula o cosseno hiperbólico de um número complexo

createComplex(double r, double i) Cria um número complexo dado sua parte real e imaginária

divide(Complex divisor) Retorna um número complexo cujo valor é (this / divisor)

Divide(double divisor) Retorna um número complexo cujo valor é (this / divisor)

equals(java.lang.Object outro) Testa se dois Complexos são iguais

exp() Calcula a função exponencial de um número complexo

getArgument() Calcula o argumento de um número complexo getField() Obtem o campo ao qual a instância pertence.

getImaginary() Retorna aparte imaginária de um número com- plexo

getReal() Retorna a parte real de um número complexo hasCode() Obter um hashCode para o número complexo isInfinity() Verifica se ambas as partes de um número com-

plexo tem um valor infinito

isNaN() Verifica se uma ou ambas as partes de um nú- mero complexo é NaN.

log() Calcula o logaritmo natural de um número com- plexo

multiplay(Complex f) Retorna um número complexo cujo valor é (this * f)

multiplay(double f) Retorna um número complexo cujo valor é (this * f)

multiplay(int f) Retorna um número complexo cujo valor é (this * f)

negate() Retorna um número complexo cujo valor é (- this)

nthRoot(int n) Calcula as n raízes de um número complexo pow(Complex x) Retorna um número complexo elevado à x pow(double x) Retorna um número complexo elevado à x reciprocal() Retorna o inverso multiplicativo

sin() Calcula o seno de um número complexo

sinh() Calcula o seno hiperbólico de um número com- plexo

sqrt() Calcula a raiz quadrada de um número com- plexo

sqrt1z() Calcula a raiz quadrada de (this -1)

substract(Complex s) Retorna um número complexo cujo valor é (this -s)

substract(double s) Retorna um número complexo cujo valor é (this -s)

tanh() Calcula a tangente hiperbólica de um número complexo

toString() Complex valueOf(double realPart) Cria um nú- mero complexo dado a parte real

valueOf(double r, double i) Cria um número complexo dado ambas as par- tes

ComplexField

Esta classe é responsável pela representação dos números complexos. É composta pelos seguintes métodos:

getInstance(): Obtém uma instância única retornando um ComplexField; getOne():Obtém a identidade multiplicativa e retorna um Complex; getRuntimeClass(): Retorna a classe runtime do FieldElement e getZero():Obtém a identidade aditiva e retorna um Complex; ComplexFormat

Esta classe é responsável pelo formato de um número complexo, Re(c) + Im(c)i. i pode ser substituído por j (ou qualquer outra coisa), e o formato de número de peças reais e imaginárias podem ser configurados.

Construtores:

1. ComplexFormat (): Cria uma instância com a parte imaginária padrão, i, e o for- mato de número padrão para ambas as partes reais e imaginárias.

2. ComplexFormat (formato java.text.NumberFormat): Cria uma instância com um formato de número personalizado para as partes reais e imaginárias.

3. ComplexFormat (java.text.NumberFormat realFormat, java.text.NumberFormat ima- ginaryFormat): Cria uma instância com um formato de número personalizado para a parte real e um formato de número personalizado para a parte imaginária.

4. ComplexFormat (imaginaryCharacter java.lang.String): Cria uma instância com um carácter personalizado imaginário, e no formato de número padrão para ambas as par- tes reais e imaginárias.

5. ComplexFormat (imaginaryCharacter java.lang.String, formato java.text.NumberFormat): Cria uma instância com um carácter personalizado imaginário, e um formato de número personalizado para as partes reais e imaginárias.

6. ComplexFormat (imaginaryCharacter java.lang.String, java.text.NumberFormat re- alFormat, java.text.NumberFormat imaginaryFormat): Cria uma instância com um carác- ter personalizado imaginário, um formato de número personalizado para a parte real, e um formato de número personalizado para a parte imaginária.

Métodos:

A Tabela 3.5 apresenta todos os métodos implementados na classe ComplexFormat: Tabela 3.5: Métodos da classe ComplexFormat

Método Função

format(Complex c) Este método chama for- mat(Object,StringBuffer,FieldPosition).

format(Complex complexo, StringBuffer sb, FieldPosi- tion pos)

Formata um objeto complexo para produzir uma string.

format(Double c) Esse método chama for-

mat(Object,StringBuffer,FieldPosition). format(Object obj, String-

Buffer sb, FieldPosition pos)

Formata um objeto para produzir uma string

getAvailableLocales() Obtêm um conjunto de localidades para as quais for- matos complexos estão disponíveis.

getImaginaryCharacter() Acessa o ImaginaryCharacter getImaginaryFormat() Formata o imaginaryFormat

getInstance() Retorna o formato padrão complexo para o local atual.

getInstance(Locale locale) Retorna o formato padrão complexo para a determi- nada localidade.

getInstance(String ima- ginaryCharacter, Locale locale)

Retorna o formato padrão complexo para a determi- nada localidade.

getRealFormat() Acessa o realFormat

parse(String source) Analisa uma string para produzir um objeto com- plexo.

parse(String source, ParsePo- sition pos)

Analisa uma string para produzir um objeto com- plexo.

3.9

Linguagens XSC

Há cinco décadas que estão sendo desenvolvidas pesquisas com o intuito de possibi- litar que máquinas suportem uma aritmética mais poderosa que a do ponto flutuante. A partir daí surgiram as linguagens XSC (eXtended Scientific Computing) que são lingua- gens para computação científica com algoritmos precisos carregando seu próprio controle de precisão.

No final da década de setenta, mais precisamente entre 1976 e 1979, duas universi- dades alemãs a Universidade Karlshure e Kaiserlautern se uniram para desenvolver uma extensão do PASCAL, que ficou conhecida como PASCAL-SC. Nos anos seguintes, jun- tamente com a IBM, foi lançada uma versão do FORTRAN 77 implementada em compu- tadores IBM/370 chamada ACRITH-SC.

A primeira geração das linguagens científicas foram as linguagens SC. As primeiras linguagens desenvolvidas foram FORTRAN-SC e PASCAL-SC, sendo esta última bas- tante citada na literatura sobre computação intervalar. Diversos pacotes foram criados para estas linguagens tanto para tarefas numéricas usuais quanto para resolução de sis-

temas lineares. Uma grande desvantagem desta linguagem é que só estavam disponíveis para uma variedade limitada de computadores [Kearfott 1996].

O desenvolvimento de novas linguagens de programação, como C++ e JAVA, torna- ram mais fácil a portabilidade das linguagens, ou seja, C++ e JAVA são capazes de se adaptar a hardwares e softwares. Deste fato surgiram as linguagens XSC, uma segunda geração de linguagens com maior exatidão com suporte a operações intervalares.

De acordo com [Dutra 2000], estas novas linguagens para computação científica têm como características principais:

• Sobrecarga de operadores,

• Agrupamento das funções em módulos específicos, • Vetores dinâmicos,

• Arredondamento direcionado,

• Tipos numéricos primitivos simples, como real, complexo e intervalo; • Operadores aritméticos de maior exatidão para os tipos numéricos e • Funções elementares de maior exatidão para os tipos numéricos.

Nas próximas subseções serão apresentadas duas destas linguagens: PASCAL-XSC e C-XSC.

3.9.1

PASCAL-XSC

A linguagem de programação PASCAL-XSC6 é uma ferramenta desenvolvida para solucionar problemas numéricos. Esta nova versão, diferente da PASCAL-SC, tem a vantagem de ser portável para outros hardwares e possui tipos de dados específicos para intervalos, números complexos e matrizes.

PASCAL-XSC foi desenvolvida na linguagem e programação C e seus compiladores são utilizados por uma variedade de computadores tais como computadores pessoais, es- tações de trabalho, mainframes e supercomputadores.

Os principais conceitos de Pascal-XSC são [Klatte et al. 1999]: • Padrão ISO do PASCAL;

• Conceito de operador universal;

• Funções e operadores com tipo de resultado arbitrário; • Sobrecarga de procedimentos;

• Rotinas de leitura e escrita; • Conceito de módulo;

• Arrays dinâmicos, acesso e subarrays; • Conceito de string;

• Arredondamento controlado; • Produto escalar ótimo;

• Tipo de padrão dotprecision e tipos aritméticos adicionais; • Aritmética de alta-exatidão para todos os tipos;

• Funções de alta-exatidão e avaliação exata de expressões; • Funções e operadores.

Esta linguagem pode implementar aplicações em módulos, cuja função é simplificar um programa (código) grande em pequenos blocos de códigos, para resolver problemas numéricos comuns, tais como:

• Sistemas de equações lineares e não-lineares; • Inversão de matrizes;

• Autovalores e Autovetores;

• Avaliação de expressões aritméticas;

• Avaliação de polinômios e busca de zeros de polinômios; • Quadratura numérica;

• Equações diferenciais; • Equações integrais; • Diferenciação automática; • Otimização.

Descrição dos tipos básicos

PASCAL-XSC é baseado na linguagem de programação PASCAL. Aqui serão apre- sentados os tipos básicos de PASCAL e as alterações que foram necessárias durante o desenvolvimento de PASCAL-XSC. Os tipos básicos em Pascal são os tipos integer, boolean, char, tipos de enumeração e subtipos. A seguir eles são definidos: [Klatte et al. 1999]

Integer: Uma constante literal do tipo integer é uma sequência de dígitos (decimais) com ou sem um sinal de + ou -. Em PASCAL-XSC, um valor do tipo inteiro pode também ser escrito como uma constante hexadecimal inicializada com o caractere $ e seguido por uma sequência de dígitos hexadecimais composto pelos dígitos 0, 1, ..., 9 e as letras A, B, ..., F e a, b, ..., f.

Real: Uma constante literal do tipo real tem a seguinte representação: ± mantissa E expoente.

A mantissa é uma sequência de dígitos com o sem ponto decimal e o expoente é um valor inteiro. A notação ’± mantissa’, onde o expoente é omitido, também é permitida.

Em Pascal-XSC, para realizar a conversão de constantes literais real dentro do for- mato de dados internos de maneira controlada, é necessária uma notação adicional para estas constantes. Enquanto a notação de real em PASCAL implica na conversão com arredondamento para o numero de ponto-flutuante mais próximo, ela possibilita a espe- cificação de constantes reais que são convertidas com arredondamento para o número de ponto-flutuante menor mais próximo ou para o maior mais próximo com notações ’(< ± mantissa E expoente)’ e ’(> ± mantissa E expoente)’ respectivamente. O E e o expoente podem ser omitidos mas os parênteses são obrigatórios.

Boolean: Este tipo é composto pelas constantes lógicas true e false, onde false < true. Char: Estas constantes são fechadas entre aspas simples. A ordem de relação é a seguinte:

’0’ < ’1’ < ... < ’9’ e ’a’ < ’b’ < ... < ’z’.

Tipos e enumeração: Este tipo consiste de constantes listadas na definição de tipos. A relação de ordem é definida pela ordem da enumeração. Um tipo de enumeração é definido pelo programador em uma definição de tipos. As constantes literais que são os elementos de uma enumeração não podem colidir com nenhum valor de outra enumera- ção.

Subtipos: Subtipos podem ser definidos pela especificação limite inferior e do limite superior (constante ... constante). O conjunto dos valores de um subtipo consiste em to- dos os valores que estão entre esses limites.

Dotprecision: PASCAL-XSC introduz esse novo tipo que é baseado no tipo real e permite a representação de produtos de dois números reais arbitrários e a adição de um número arbitrário de tais produtos em um formato de ponto-flutuante fixo de tamanho adequado. Se o formato real interno é fixado pela mantissa de tamanho l e os expoen- tes máximo (emax) e mínimo (emin) então uma variável dotprecission ocupa espaço de armazenamento da forma

Figura 3.2: Tamanho de uma variável do tipo dotprecision

O tamanho total é: L = g + 2emax + 2|emin| + 2l dígitos, onde g denota o número de dígitos guardados na acumulação de carga durante a adição.

Valores do tipo dotprecision tipicamente ocorrem durante a multiplicação de vetores e matrizes.

Os Tipos Intervalo e Complexo

PASCAL-XSC provê uma aritmética adicional para os tipos complex, interval e cin- terval. Eles não possuem constantes nem operadores como sua linguagem, portanto, tam- bém não há expressões. O uso de operadores e funções padrões requer o uso dos módulos aritméticos correspondentes (C_ARI, I_ARI e CI_ARI, respectivamente).

O tipo complex: O número complexo z= x + iy, com x sendo a parte real e y a parte imaginária podem ser declaradas em PASCAL como:

type complex = record re, im: real end;

Em PASCAL-XSC, este tipo é um tipo pré-definido. A declaração da variável var z:complex;

especifica uma variável complexa z. As partes real e imaginária de z podem ser aces- sadas por z.re e z.im, respectivamente.

a= [a, a] :={x ∈ R|a ≤ x ≤ a}

com a sendo o limite inferior e a o limite superior, PASCAL-XSC provê um tipo intervalpré-definido, declarado da seguinte forma:

type interval = record inf, sup: real end; A declaração de variável

var a: interval;

especifica uma variável a do tipo intervalo. Os limites superior e inferior podem ser acessados por a.inf e a.sup, respectivamente.

O tipo cinterval: Intervalos complexos são retângulos com lados paralelos aos eixos no plano complexo. O tipo pré-definido cinterval é definido por:

type cinterval: record re, im: interval end; As partes de um complexo intervalar c, declarado como

var c: cinterval;

podem ser acessados por c.re (um intervalo para a parte real) e c.im (um intervalo para a parte imaginária). Os seus limites podem ser acessados por c.re.inf, c.re.sup, c.im.inf e c.im.sup.

3.9.2

C-XSC

Segundo [Hofschuster & Krämer 2010], a linguagem C-XSC7é uma ferramenta bas-

tante poderosa e fácil de ser manuseada. Esta linguagem tem como principal objetivo auxiliar no desenvolvimento de algoritmos numéricos que necessitam de alta precisão. As características, ou tipos, mais importantes em C-XSC são os tipos real, complexo, in- tervalo e complexo intervalar.

A escolha da linguagem de programação C++ ao invés de C se dá pelo fato que esta segunda não ser apropriada para programar algoritmos numéricos, já que não fornece as estruturas de dados numéricas básicas como vetores e matrizes e não faz a checagem da indexação em arrays [Wiethoff 1996]. Já a linguagem C++, que é uma extensão da C

orientada à objetos, fornece várias facilidades que suprem as deficiências da C, já que agora a linguagem apresenta o conceito de classes e sobrecarga de operadores.

As características básicas da C-XSC são:

• Tipos de dados real (real), complexos (complex), intervalo (interval) e complexo intervalar (cinterval);

• Fornece uma notação específica para manipular subarrays de vetores e matrizes tornando-os tipos dinâmicos;

• Dotprecision, ou seja, tipos com precisão após a vírgula; • Maior precisão em operadores aritméticos pré-definidos; • Funções padrões de alta ocorrência;

• O controle de arredondamento durante operações de entrada e saída de dados se dá pelo conceito de sobrecarga dos operadores << e >> da C++. Sendo assim, é possível especificar o número de casas decimais do valor impresso.

• Fornece uma aritmética dinâmica de múltipla precisão, como o real longo (l_real) e o intervalo longo (l_interval), bem como também são implementados vetores dinâmicos correspondentes a matrizes, incluído operações vetoriais.

• Fornece uma biblioteca para resolução de problemas, que nada mais é do que uma coleção de rotinas de problemas padrões para análises numéricas, com isto, garante resultados de alta precisão.

Descrição dos tipos básicos

C-XSC provê os tipos de dados numéricos simples como real, interval, complex e cinterval. Cada um com suas próprias aritméticas, operadores relacionais e funções arit- méticas padrão. Todos os operadores aritméticos pré-definidos fornecem resultados com uma precisão de pelo menos 1 ulp(unidade na última casa decimal), desta forma é possí- vel ter a máxima precisão na computação científica nos seus tipos.

O arredondamento dos operadores aritméticos pode ser controlado usando os tipos intervale cinterval. Funções estão disponíveis para todas as combinações matematica- mente úteis. Constantes literais podem ser convertidas com a máxima exatidão. Todas as funções matemáticas padrão para os tipos de dados numéricos podem ser chamados por seus nomes genéricos e fornecem resultados com garantia de alta precisão para argumen- tos arbitrários admissíveis.

Os tipos em C-XSC são definidos da seguinte forma:

Real: De acordo com [C-XSC 2010], a aritmética de C-XSC é baseada no padrão IEEE para aritmética binária de ponto-flutuante. O tipo de dados real consiste de todos os tipos de ponto-flutuante e valores especiais especificados pelo padrão para números de ponto-flutuante com mantissa de tamanho duplo. Portanto, um número do tipo real tem 64-bit, e a base b do sistema de ponto-flutuante, R = R(b,l,emin, emax), é 2.

Se o compilador de C de um computador não está conforme o padrão, o tipo real uti- liza sua própria aritmética IEEE de ponto flutuante. Portanto, a introdução de um novo tipo de dados é necessário para que se tenha a portabilidade.

Estrutura: Um esboço de um ponto-flutuante é observado na Figura abaixo:

Figura 3.3: Formato de um ponto-flutuante

O bit mais significativo o bit de sinal e é denotado por s. Se ele é um, o número de ponto-flutuante não zero é negativo, caso contrário é positivo. Os outros 63 bits são divi- didos entre a mantissa e o expoente.

Mantissa:O tamanho da mantissa, l, de um número real contém 53 bits. O bit 53 não é explicitamente armazenado. Este valor depende da normalização ou desnormalização na representação de um ponto-flutuante. Com este tamanho de mantissa, números decimais

com um máximo de 15 dígitos fracionários podem ser representados com alta exatidão. Uma vez que um formato binário de ponto-flutuante é usado, é impossível armazenar to- dos os números decimais precisamente. No entanto, pode-se ter constantes decimais com arredondamento controlado dentro de uma variável do tipo real.

Expoente: O expoente e de um ponto-flutuante é armazenado em um campo de 11 bits. Um valor de 1023 é subtraído do valor armazenado para obter o valor do expo- ente real. Isto produz emin= −1022 e emax= 1023. Convertendo para o sistema decimal

−308 ≤ e ≤ 308.

Complex: Este tipo é utilizado para armazenar números complexos z= x + iy ∈ C, onde x denota a parte real, y a parte imaginária e i denota a unidade imaginária√−1.

Interval: Este tipo é utilizado para representar intervalos sobre os números reais de ponto-flutuante:

[a] = [a, a] ={x ∈ R|a ≤ x ≤ a ∈ R}

ou seja, a representa o conjunto de todos os números fechados entro dos limites a, a ∈ R. A notação a o limite inferior e a denota o limite superior do intervalo [a].

Cinterval: Este tipo de dado é utilizado para armazenar complexos intervalares. Eles são definidos como retângulos da forma z = [x] + i[y] ∈ C, onde a parte real [x] ∈ C e a parte imaginária [y] ∈ C, com partes paralelas aos eixos no plano complexo, como indica a Figura 3.4.

Figura 3.4: Complexo Intervalar [3.0,4.5] + i[1.0,2.0]

Dotprecision: Os tipos dotprecision, idotprecision, cdotprecision e cidotprecision são baseados nos tipos de dados real, interval, complex e cinterval respectivamente. Variáveis

Documentos relacionados