MonografiaIC1

Propaganda
Universidade Federal de Pernambuco
Centro de Informática
CALCULADORA INTERVALAR EM JAVA
Renato Viana Ferreira
Recife, 2005
Universidade Federal de Pernambuco
Centro de Informática
CALCULADORA INTERVALAR EM JAVA
Renato Viana Ferreira
Orientadora: Marcília Andrade Campos
Monografia apresentada à disciplina Iniciação Científica 1 do curso de
graduação em Ciência da Computação da UFPE
Recife, 2005
Identificação
Universidade Federal de Pernambuco
Aluno: Renato Viana Ferreira
CPF: 057.347.140-58
Curso: Bacharelado em Ciência da Computação
Título: Calculadora Intervalar em Java
Orientadora: Marcília Andrade Campos
Resumo
Sistemas computacionais atuais são incapazes de representar todos os números reais,
pois estes são contínuos e densos e a representação digital é discreta. A representação
destes números é realizada em computadores por meio de ponto flutuante, que provê
uma representação binária capaz de armazenar uma quantidade finita de valores em sua
forma exata e todos os outros valores devem ser aproximados para o valor representável
mais próximo. Java se tornou a linguagem mais utilizada no mundo devido ao seu
paradigma de programação, portabilidade, simplicidade e robustez. Por isso, foi
desenvolvida uma extensão para computação científica para Java, chamada Java-XSC
(eXtension for Scientific Computation), no intuito de solucionar o problema de erro
numérico em Java. Com relação à extensão intervalar para Maple, o intpakX, a
biblioteca Java-XSC apresentou ótimos resultados após testes de validação,
apresentando saídas semelhantes na grande maioria dos casos e também de melhor
precisão em algumas operações. Uma calculadora intervalar para Java foi implementada
como uma aplicação para a biblioteca, não apenas contendo as operações aritméticas,
mas também lógicas.
Índice
1.
2.
a.
b.
c.
3.
4.
6.
7.
Introdução ................................................................................................................. 6
Revisão Bibliográfica ............................................................................................... 7
Ponto-flutuante em Java ........................................................................................... 7
Erros de Ponto-Flutuante .......................................................................................... 7
Implementação de Ponto-Flutuante em Java ............................................................ 8
Objetivos................................................................................................................... 9
Metodologia ............................................................................................................ 10
Discussões e Conclusões ........................................................................................ 14
Referências ............................................................................................................. 15
1. Introdução
Muitos avanços científicos das últimas décadas não seriam possíveis sem a
computação de ponto-flutuante dos computadores digitais [Bush, 1996]. Porém, alguns
resultados de computação utilizando ponto-flutuante parecem estranhos mesmo para
pessoas com vários anos de experiência em computação científica e computacional.
Um grande problema enfrentado pelo modelo computacional atual é a
representação numérica, devido à continuidade e densidade dos números reais. Estes
números não podem ser representados de maneira discreta em sua totalidade, então são
representados através de números de ponto-flutuante, que representam uma parcela de
valores de maneira exata.
A computação de ponto-flutuante trabalha internamente com base 2, binária. Por
exemplo, a fração decimal 0.1 não pode ser representada de maneira exata na base 2.
Ela é uma dízima periódica 0.00011001100110... Assim como 1/3 = 0.33333… na base
10. Quando somamos 0.333333... com 0.666666... temos 0.999999... ao invés de 1.0,
apesar de termos somado 1/3 + 2/3 para obter 1. Então, na base 2, quando somamos 0.1
+ 0.1 obtemos algo diferente de 0.2.
Uma conclusão crucial é que ponto-flutuante é inexato por natureza [Green,
R.,2005], por que nenhuma representação digital é capaz de lidar com todos os números
reais É importante notar que como sistemas digitais conseguem representar uma parcela
finita dos números reais , todos os outros valores são aproximados para o valor
representável mais próximo [Microsoft, 2003] [IEEE, 1985].
A seção 2 desta dissertação apresenta uma revisão bibliográfica com exemplos
de erros de ponto-flutuante que ocorrem na linguagem Java. A terceira seção apresenta
os objetivos deste projeto. A quarta seção descreve a metodologia de desenvolvimento
do projeto seguida da seção de resultados. As conclusões e discussões são apresentadas
na seção 6, finalizando o documento com as referências.
2. Revisão Bibliográfica
a. Ponto-flutuante em Java
Java ganhou enorme popularidade desde que foi criada. Sua rápida ascensão e
larga aceitação remetem às possibilidades fornecidas para design e programação,
principalmente à promessa de compilar o código uma única vez e rodar em qualquer
plataforma. Como descrito nos White papers de Java: “Java é simples, orientada a
objetos, distribuída, interpretada, robusta, segura, adaptável a arquiteturas, portável,
multithreaded e dinâmica” [Choudhari, P., 2001] [Sun Microsystems, 2005].
Java oferece herança de forma simples, com o uso de interfaces e eliminou o uso
de ponteiros, quando comparado com C++. Outra vantagem para os programadores Java
é que a JVM (Java Virtual Machine) automaticamente gerencia a alocação de memória
e coleta de lixo.
Devido a tudo isso, Java, atualmente é a linguagem de programação mais
popular do mundo.
b. Erros de Ponto-Flutuante
Para representar números de ponto-flutuante Java oferece dois tipos primitivos,
float e double e duas classes wrapper Float e Double do pacote java.lang [Sun
Microsystems, 2005]. O tipo primitive double dá suporte a 16 dígitos decimais, porém
apenas precisão para os 14 mais significativos [Gosling, J., Joy, B., Steele G., 1996].
Exemplos de erros de ponto-flutuante são mostrados abaixo:
Exemplo 1:
Esse exemplo mostra uma simples subtração entre dois números de pontoflutuante, depois compara o resultado obtido com o resultado esperado e imprime o
resultado da comparação.
double d = 3.9-3.8;
if(d==0.1) System.out.println("equals");
else System.out.println("not equals");
A saída deveria ser claramente equals na stdout (standard output), porém
imprime not equals, pois d é igual a 0.10000000000000009, mostrando que a
subtração retornou um valor incorreto.
Exemplo 2:
Este exemplo executa dez adições seqüenciais a uma variável e imprime o
resultado final.
double d = 0.0;
for(int i = 0; i < 10; i++){
d += 0.4;
}
System.out.println(d);
Fazemos um loop que adiciona 0.4 dez vezes à variável d, então ela deveria
assumir o valor de 10 x 0.4, que é obviamente 4.0, mas o número impresso na saída foi
3.9999999999999996.
Para computação científica, que exige alta precisão, esta margem de erro nem
sempre aceitável, pois causa resultados errados, o erro deve ser controlado [Ferreira, R.
V., Fernandes, B. T., Campos, M. A., 2004].
c. Implementação de Ponto-Flutuante em Java
A implementação de ponto-flutuante em Java segue parcialmente o padrão IEEE
754 (1985) para aritmética de ponto-flutuante [The Macaulay Institute, 2004]. Como
dito previamente, os tipos primitivos de Java para ponto-flutuante são float e double,
representando a precisão simples de 32 bits e precisão dupla de 64 bits do formato IEEE
754 como especificados no IEEE Standard for Binary Floating-Point Arithmetic,
ANSI/IEEE Standard 754-1985 (IEEE, New York). A representação binária para o tipo
float é:
1 bit
8 bits
23 bits
sign
exponent significand
e para o tipo double é:
1 bit
11 bits
52 bits
sign
exponent significand
A representação float dá precisão de 6 a 9 dígitos, enquanto double dá de 15 a 17
dígitos de precisão.
O problema da implementação de ponto-flutuante em Java é que Java não
cumpre todos os requisitos do padrão IEEE 754. Os três principais problemas são:
1. Não suporta os bits de exceção do IEEE 754.
2. Não provê os arredondamentos direcionados.
3. Não provê um tipo intervalar de máquina.
Os bits de exceção são: Invalid Operation, Overflow, Division-by-Zero,
Underflow, Inexact Result. Sem estes bits é impossível se adequar ao padrão IEEE 754
[The Macaulay Institute, 2004].
3. Objetivos
O objetivo deste projeto é desenvolver uma API (Application Programming
Interface) chamada Java-XSC (eXtension for Scientific Computation) que provê
controle automático dos erros de ponto flutuante. Implementando:
 Arredondamentos direcionados;
 O tipo intervalo;
 Operações da matemática intervalar;
 Uma calculadora intervalar;
Como Java, atualmente, é linguagem mais popular do mundo, devido a um
grande número de vantagens oferecidas, como: simplicidade, portabilidade e robustez,
tende a ser mais utilizada em aplicações de computação científica. Visa-se suprir essa
necessidade, com a implementação de uma biblioteca chamada Java-XSC (eXtension
for Scientific Computation) para controlar erros numéricos de ponto-flutuante utilizando
métodos da matemática intervalar [Moore, R. E. (1996)].
4. Metodologia
Este projeto tem a coordenação da professora Marcília Andrade Campos
(www.cin.ufpe.br/~mac) no Centro de Informática da Universidade Federal de
Pernambuco e conta com a participação de quatro alunos, sendo dois de mestrado e dois
da graduação em Ciência da Computação.
O primeiro passo para o desenvolvimento de uma biblioteca intervalar para Java
(Java-XSC) foi o estudo de arredondamentos direcionados, tanto para cima, como para
baixo. Em seguida, uma classe Rounding foi modelada e implementada contendo os
arredondamentos e foi validada utilizando a biblioteca intervalar para Maple, intpakX,
desenvolvida no Departamento de Matemática da Universidade de Wuppertal na
Alemanha.
Após a documentação da classe Rounding, foi discutida a criação do tipo
intervalo, sobre duas possibilidades: a inserção de um tipo primitivo na linguagem Java
ou a criação de uma classe. Verificando-se a impossibilidade de inserção de tipos
primitivos na linguagem devido a restrições técnicas e legais, foi modelada e
implementada a classe Interval para representar o tipo intervalo contendo seus limites
superior e inferior e a precisão desejada.
Posteriormente foi feito um estudo sobre operações intervalares, tanto unárias,
como lógicas e aritméticas, estes estudos foram realizados através de revisão
bibliográfica de teses e artigos relacionados ao tópico e utilização da biblioteca intpakX.
As operações unárias foram implementadas na própria classe Interval, pois se
referem unicamente a um intervalo. Para a implementação das operações aritméticas foi
criada a classe IntervalMath e para as operações lógicas, a classe IntervalSet.
Toda a modelagem das classes foi realizada utilizando o Rational Rose
Entreprise Edition da Rational/IBM. O desenvolvimento da biblioteca utilizou as
versões 1.4.2 e 5.0 de Java e a IDE (Ambiente Integrado de Desenvolvimento) Eclipse,
nas versões 2.1, 3.0 e 3.1.
5. Resultados
Durante este projeto foi modelada, implementada, documentada e validada uma
extensão para computação científica para a linguagem de programação Java. Por fim,
também foi implementada uma aplicação para esta biblioteca que foi uma calculadora
intervalar.
Os arredondamentos direcionados implementados na classe Rounding, quando
comparados às funções de arredondamento do intpakX, apresentaram resultados
extremamente satisfatórios, obtendo saídas idênticas em 70% dos casos de teste. A
diferença nos resultados, quando ocorreu, foi sempre apresentada na última casa
decimal, onde em relação à qualidade do arredondamento, ou seja, a menor distância
entre o número inicial a ser arredondado e o resultado da função de arredondamento,
ocorreu um relativo empate entre o intpakX e a biblioteca Java-XSC.
A definição do tipo intervalo foi feita considerando o limite inferior e superior e
também a precisão desejada para os arredondamentos, no que Java-XSC difere do
intpakX, pois a precisão deste último é invariável. Os limites foram representados pelo
tipo primitivo double (ponto-flutuante) e a precisão pelo tipo primitivo int (inteiro).
Sobre o tipo intervalo, modelado como uma classe chamada Interval, foram
implementadas as seguintes operações unárias: (i) Comprimento; (ii) Simétrico; (iii)
Recíproco; (iv) Verificação do vazio.
As operações aritméticas intervalares, implementadas na classe IntervalMath,
foram as seguintes: (i) Igualdade (implementada na classe Interval); (ii) Adição; (iii)
Subtração; (iv) Multiplicação; (v) Divisão.
As operações lógicas intervalares, implementadas na classe IntervalSet, foram:
(i) Pertence (implementada na classe Interval); (ii) Interseção, (iii) União, (iv) Absoluto,
(v) Distância.
A comparação dos resultados de Java-XSC com o intpakX, para as mesmas
entradas, foi extremamente satisfatória, tendo a biblioteca Java-XSC apresentado um
controle do erro bastante similar e se mostrando mais precisa em alguns casos,
principalmente na operação de divisão. As operações de distância e absoluto não foram
encontradas na biblioteca intpakX, impossibilitando a comparação.
A calculadora intervalar para Java foi implementada como uma aplicação para a
biblioteca e será disponibilizada na web, não apenas contendo as operações aritméticas,
mas também lógicas.
Aqui estão os resultados gerados pela biblioteca Java-XSC, comparados com o
MapleInt:
Java - XSC
MapleInt
Arredondamento para baixo: 2.0 com precisão de 10-9
1.999999999
1.999999999
Arredondamento para baixo: 3.88888888899 com precisão de 10-9
3.888888888
3.888888888
Arredondamento para baixo: -1.6564564876648 com precisão de 10-9
-1.656456488
-1.656456489
Arredondamento para cima: 2.0 com precisão de 10-9
2.000000001
2.000000001
Arredondamento para cima: 3.88888888899 com precisão de 10-9
3.888888890
3.888888890
Arredondamento para baixo: -1.6564564876648 com precisão de 10-9
-1.656456486
-1.656456487
Comprimento de [1.0, 2.5]
1.5
1.5
Comprimento de [0.0, 8.9]
8.9
8.9
Comprimento de [-5.6, 4.9]
10.5
10.5
Recíproco de [-3.0, 8.4] com precisão de 10-9
[-Infinity, Infinity]
[-Infinity, Infinity]
Recíproco de [-5.0, -2.0] com precisão de 10-9
[-0.500000001, -0.199999999]
[-0.500000001, -0.199999999]
Recíproco de [1.0, 4.0] com precisão de 10-9
[0.249999999, 1.000000001]
[0.249999999, 1.000000001]
0.0 pertence a [-0.1, 0.1]
true
true
0.2 pertence a [-0.1, 0.1]
false
false
0.1 pertence a [-0.1, 0.1]
true
true
Adição: [1.0, 2.5] + [0.0, 8.9] com precisão de 10-9
[0.999999999, 11.400000001]
[0.999999999, 11.400000001]
Adição: [-8.9, 0.0] + [0.0, 8.9] com precisão de 10-9
[-8.900000001, 8.900000001]
[-8.900000001, 8.900000001]
Subtração: [-8.9, 0.0] - [0.0, 8.9] com precisão de 10-9
[-0.000000001, 17.800000001]
[0.000000000, 17.800000001]
Subtração: [1.0, 3.0] - [4.0, 5.0] com precisão de 10-9
[-4.000000001, -0.999999999]
[-4.000000001, -0.999999999]
Multiplicação: [1.0, 3.0] * [4.0, 5.0] com precisão de 10-9
[3.999999999, 15.000000001]
[3.999999999, 15.000000001]
Multiplicação: [-8.9, 0.0] * [1.0, 2.5] com precisão de 10-9
[-22.250000001, 0.000000001]
[-22.250000001, 0.000000000]
Divisão: [-8.9, 0.0] / [1.0, 2.5] com precisão de 10-9
[-Infinity, Infinity]
[-Infinity, Infinity]
Divisão: [4.0, 5.0] / [1.0, 2.5] com precisão de 10-9
[1.599999999, 5.000000001]
[1.599999999, 5.000000006]
Tabela 1: Resultados da biblioteca Java-XSC confrontados aos do MapleInt
Diagrama UML de relação entre as classes da biblioteca:
Diagrama 1: Diagrama de classes atual da biblioteca Java-XSC
6. Discussões e Conclusões
Sistemas computacionais atuais são incapazes de representar todos os números
reais, pois estes são contínuos e densos e a representação digital é discreta. Java, sendo
uma linguagem de programação, conseqüentemente, sofre esse problema, além disso, a
implementação de ponto flutuante para Java desprezou fatores importantes como: (i)
não suportar flags de exceções, definidos pelo padrão IEEE 754, (ii) não prover os
arredondamentos direcionados também definidos pelo IEEE 754 e (iii) não prover
intervalos como tipo primitivo. Portanto, Java apresenta vários erros em operações com
ponto-flutuante.
Como Java, atualmente, é linguagem mais popular do mundo, devido a um
grande número de vantagens oferecidas, como: simplicidade, portabilidade e robustez,
tende a ser mais utilizada em aplicações de computação científica. Visando suprir essa
necessidade, foi implementada uma biblioteca chamada Java-XSC (eXtension for
Scientific Computation) para controlar erros numéricos de ponto-flutuante utilizando
métodos da matemática intervalar.
Com relação à extensão intervalar para Maple, o intpakX, a biblioteca Java-XSC
apresentou ótimos resultados após testes de validação, apresentando saídas semelhantes
na grande maioria dos casos e também de melhor precisão em algumas operações.
A aplicação implementada para uso da biblioteca foi uma calculadora intervalar
para operações aritméticas e lógicas que será disponibilizada na internet através do site
do projeto, http://www.cin.ufpe.br/~javaxsc/.
A biblioteca Java-XSC será estendida para conter, além das operações
aritméticas e lógicas, as operações logarítmicas, trigonométricas e estatísticas da
matemática intervalar, além das relações de ordem.
7. Referências
Bush, B.M., (1996), “The Perils of Floating Point”, http://www.lahey.com/float.htm,
visitado em Novembro, 2005.
Green, R., (2005), “Java Glossary: Floating Point”,
http://mindprod.com/jgloss/floatingpoint.html, visitado em Novembro, 2005.
Microsoft (2003), “Tutorial to Understand IEEE Floating-Point Errors”,
http://support.microsoft.com/kb/q42980/, visitado em Novembro, 2005.
IEEE Computer Society (1985), "IEEE Standard for Binary Floating-Point Arithmetic",
IEEE Std 754-1985.
Choudhari, P., (2001), “Java Advantages & Disadvantages”,
http://arizonacommunity.com/articles/java_32001.shtml, visitado em Novembro,
2005.
Sun Microsystems, “Java Language Overview”, Java 2 Platform, Standard Edition,
White Papers, http://java.sun.com/docs/overviews/java/java-overview-1.html,
visitado em Novembro, 2005.
Sun Microsystems, “JavaTM 2 Platform, Standard Edition, v 1.4.2 API Specification”,
http://java.sun.com/j2se/1.4.2/docs/api/, visitado em Novembro, 2005.
Gosling, J., Joy, B., Steele G., (1996), “The Java Language Specification”, Addison
Wesley.
Ferreira, R. V., Fernandes, B. T., Campos, M. A., (2004), “Evaluating the floating-point
in Java Virtual Machine”, Anais ENNEMAC 2004.
The Macaulay Institute, (2004), “Floating Point Arithmetic and Java”,
http://www.macaulay.ac.uk/fearlus/floating-point/javabugs.html,
visitado
em
Novembro, 2005.
Knuth, D., (1997) “The Art of Computer Programming”, Volume 2.
Moore, R. E. (1996), “Interval Analysis” Englewood Cliffs: Prentice-Hall
Campos, M. A., (1997), “Uma Extensão Intervalar para a Probabilidade Real”
Departamento de Informática – UFPE
IBM Rational Software, (2002) – Rational Rose Enterprise Edition – http://www306.ibm.com/software/rational/offerings/reqanalysis.html, visitado em Novembro,
2005
Eclipse.org, (2005) – http://www.eclipse.org/, visitado em Novembro, 2005.
MapleSoft.com, http://www.maplesoft.com/, visitado em Novembro, 2005.
Download