Lightweight Java Decimal Classe

votos
12

Estou pensando em escrever duas alternativas de precisão limitada para BigDecimal, nomeadamente DecimalInt e DecimalLong. Estes seriam capazes de lidar com números dentro dos limites reais de int e longo com um número arbitrário de casas decimais, criáveis ​​tanto na forma mutável e imutável. Meu plano é fazer com que o suporte DecimalInt +/- 999.999.999 a +/- 0,999999999 e DecimalLong o mesmo, mas com até 18 dígitos.

Isso seria feito através da manutenção de um valor de contagem dígito decimal de 0-9 para DecimalInt e 0-18 para DecimalLong ao lado do valor real armazenado como um int dimensionado ou longa. O uso normal seria para um pequeno número de casas decimais como por dinheiro e ações preços, tipicamente 2-4 casas decimais.

Os requisitos essenciais são (a) pegada magra (2 aulas, além de OverflowException), e (b) o apoio total de todas as operações básicas além de todas matemática que faz sentido.

Googling para resultados não encontrou nenhum sucessos óbvios - todos eles pareciam pertencer a decimais arbitrárias.

Minhas perguntas são: Será que isso já foi feito? Há escondido sutilezas neste que é por isso que já não tenha sido feito? Alguém já ouviu falar rumores de Java que suportam um tipo decimal como DotNet de.

EDIT: Isso é diferente de BigDecimal porque ele deve ser (a) um inferno de muito mais eficiente para não lidar com uma série de inteiros, e (b) que não vai quebrar BigInteger por isso vai ser mais magro na memória também, e (c) ele terá uma opção mutável por isso vai ser mais rápido lá também. Em resumo - menos sobrecarga para os casos de uso simples, como Eu quero armazenar um saldo bancário sem a sobrecarga de BigDecimal e a imprecisão da dupla.

EDIT: Eu pretendo fazer toda a matemática usando int ou longo para evitar o problema clássico de: 1586,60-708,75 = 877,8499999999999 em vez de 877,85

Publicado 09/12/2008 em 21:05
fonte usuário
Em outras línguas...                            


5 respostas

votos
12

Eu suspeito fortemente a razão por que isso não foi feito é que a sobrecarga de BigDecimal e BigInteger não é tão relevante quanto você pensa, e evitá-lo não vale o esforço eo risco de errar, de alguma forma sutil.

Para usar o seu exemplo: para qualquer aplicação financeira, poupando algumas dezenas de bytes é um não-problema e precisão limitada um deal-breaker (os preços das ações Meu têm tipicamente 2-4 dígitos nos EUA, mas se você quer lidar com os mercados emergentes , você vai encontrar moedas com inflação descontrolada, onde uma soma de 15 dígitos, você compra metade de um pedaço de pão).

Basicamente, parece apenas outro caso de otimização prematura.

Respondeu 11/12/2008 em 11:39
fonte usuário

votos
1

A maioria das pessoas que estão particularmente preocupados com erros de arredondamento usar BigDecimal e BigInteger que executa bem o suficiente na maioria das situações.

No entanto, casos em que o desempenho é mais crítica, usando duplo com arredondamento faz o trabalho. Isso é muitas vezes esquecido por iniciantes, mas você não pode simplesmente tomar um resultado duplo sem rodada sensata e espera obter uma resposta sensata.

Na grande maioria dos casos duplica com arredondamento é tudo que você precisa.

System.out.printf("%.2f%n", 1586.60-708.75);

impressões

877.85
Respondeu 24/11/2010 em 00:03
fonte usuário

votos
0

Se você está olhando para um pequeno número fixo, de casas decimais para a manipulação de dinheiro, então isso geralmente é feito segurando inteiro (longa se necessário) número de centavos, ou centésimos de centavo.

Se você está lidando com dinheiro, então você terá que ter o cuidado de como você lida com arredondamento. Se os seus cálculos vão ser auditados existem regras de como esse tipo de coisa é feito. Também eu suponho que você está ciente de que algumas operações não pode ser feito com precisão (divisão é o exemplo óbvio).

Respondeu 10/12/2008 em 15:38
fonte usuário

votos
0

Se o seu foco é para dispositivos portáteis olhar real . Real permite a precisão do número a ser definido de 0 a 16. Ele é projetado para telefones celulares MIDP.

Também de interesse, olhar para o reais construtiva biblioteca. Não é leve embora.

Em referência ao comentário abaixo, você não pode usar a biblioteca Commons Math Apache para trabalhar com frações? Existe alguma razão que não vai funcionar?

Respondeu 09/12/2008 em 21:31
fonte usuário

votos
-1

Parece-me que se você quiser precisão arbitrária, então você vai precisar de um número indefinido de bits para representar a mantissa. Isso significa que algum tipo de estratégia de alocação de matriz é vai ser necessário para a mantissa. Você poderia criar o seu próprio aqui, mas BigInteger faz bastante eficiente e funciona

Você precisa especificar o que o menor valor (não-zero) que você precisa para representar é. Este será de 10 ^ - (2 ^ n), em que n + 1 é o número de bits que atribuem ao expoente. Com BigDecimal é 10 ^ - (2 ^ 31). Você poderia usar um expoente tamanho arbitrário, mas nesse intervalo deve ser suficiente para qualquer um.

Então, o que você precisa é uma mantissa inteiro ilimitada para dar-lhe a precisão arbitrária, e um expoente de tamanho fixo, dependendo do que você deseja que o seu valor mínimo representável ser. Essencialmente, este é BigDecimal; a única mudança é que você vai usar algum objeto menor, em vez da int usada por BigDecimal. Eu duvido que a economia de espaço valem a pena. Gostaria de pensar que BigDecimal vai fazer o que você precisa com quase nenhum uso de memória mais do que qualquer solução que você criar a si mesmo.

Claro que você poderia escolher um número máximo de algarismos significativos que você precisa; então você precisa de armazenamento de tamanho fixo para ambos mantissa e expoente, e isso é muito menos armazenamento. Basta usar um número fixo de longs como a mantissa.

Respondeu 09/12/2008 em 23:43
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more