AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78609545
Accepted
dssof
dssof
Asked: 2024-06-12 04:02:34 +0800 CST2024-06-12 04:02:34 +0800 CST 2024-06-12 04:02:34 +0800 CST

Qual tipo de dados devo usar para lidar com um ERP: BigDecimal ou Double em Java?

  • 772

Atualmente estou desenvolvendo um sistema ERP (Enterprise Resource Planning) e preciso tomar decisões quanto ao tipo de dados a serem usados ​​para lidar com cálculos e outros valores numéricos dentro da aplicação.

Eu sei que Java oferece diversas opções para lidar com números decimais, como BigDecimal e Double. Entendo que cada um tem suas vantagens e desvantagens, mas quero garantir que escolho o mais adequado para manter a precisão e a eficiência em meu sistema.

Aqui estão alguns contextos específicos onde preciso aplicar cálculos:

  • Faturamento e Pagamentos: lidar com preços, impostos, descontos, etc.
  • Folha de pagamento e contabilidade:
  • Gestão de estoque: Incluindo preços unitários e custos de produtos.

Estou inclinado a usar o BigDecimal para operações financeiras devido à precisão que oferece, mas estou preocupado com o impacto no desempenho. Por outro lado, Double pode ser mais eficiente em termos de velocidade, mas pode introduzir erros de arredondamento.

Que recomendações você tem para lidar com esses casos em um ERP? Em quais situações seria preferível usar BigDecimal e quando Double? Existem padrões ou práticas recomendadas que devo seguir?

java
  • 3 3 respostas
  • 85 Views

3 respostas

  • Voted
  1. Best Answer
    Basil Bourque
    2024-06-12T04:41:50+08:002024-06-12T04:41:50+08:00

    Evite ponto flutuante por dinheiro

    A tecnologia de ponto flutuante troca precisão por velocidade de execução.

    Em Java, os tipos primitivos floate doublesão tipos de ponto flutuante. O mesmo acontece com suas classes wrapper Floate Double. Nunca use-os onde a precisão é importante. Isso significa nunca por dinheiro.

    Use um BigDecimalou números inteiros

    Em vez disso, quantias fracionárias de dinheiro devem ser tratadas de acordo com uma destas abordagens:

    • Use BigDecimalobjetos. Esse tipo é muito mais lento que o ponto flutuante, mas preciso. A sintaxe é mais desajeitada que os literais numéricos, é claro. Mas por outro lado, além da precisão, você obtém métodos úteis, como Banker's Rounding .
    • Mova a vírgula decimal por multiplicação para obter um número inteiro. Por exemplo, para rastrear USD até o centavo , multiplique por 100 para obter centavos (¢) como valores inteiros ( long). Para rastrear o dólar até o décimo de centavo, multiplique por mil para representar moinhos (₥).
    • Use uma biblioteca com classes que representam dinheiro. Uma dessas bibliotecas é Joda-Money , outra é JavaMoney . Adicionar tal estrutura ao próprio Java foi considerado e pode ser considerado novamente .

    Tabela de tipos de dinheiro fracionário

    Tipo Exemplo Notas Prós Contras
    Ponto flutuante
    float&double
    1.23d Nunca use por dinheiro Execução rápida. Uso conveniente como literais. Impreciso.
    GrandeDecimal new BigDecimal( "1.23" ) Representa com precisão valores fracionários. Métodos úteis, como o Arredondamento do Banqueiro. Lento. Sintaxe desajeitada.
    Inteiro inteiro
    int&long
    long cents = new Double( 1.23d * 100 ).longValue() ; Requer que você multiplique entradas fracionárias e divida para obter resultados fracionários. Execução rápida. Tipo simples, com tipos de correspondência direta no banco de dados. Pode ser confuso para programadores e usuários ingênuos. (Certifique-se de rotular de forma clara e consistente, como centsou mills.)
    Biblioteca Joda-Money Money money = Money.parse("USD 23.87") ; Construído explicitamente para o problema de lidar com quantias de dinheiro e matemática. Lida com precisão fixa e precisão variável Não padronizado.
    • 4
  2. Simulant
    2024-06-12T04:17:07+08:002024-06-12T04:17:07+08:00

    Para todos os tipos de cálculos relacionados a dinheiro, seria descuidado não usar BigDecimal. Por favor, use BigDecimalpara todos os seus cálculos.

    O que acontece se você não fizer isso? A precisão imprecisa de double/ Doublepode levar a resultados simplesmente errados ao realizar qualquer tipo de operação matemática. Resultados errados podem custar dinheiro, credibilidade e tempo à sua empresa para corrigir cálculos errados.

    O desempenho provavelmente não será um problema. Resolva problemas de desempenho apenas quando eles surgirem e não faça pré-otimização para um problema que não existe.

    • 3
  3. Girdhar Singh Rathore
    2024-06-12T04:40:48+08:002024-06-12T04:40:48+08:00

    BigDecimal: Use para todos os cálculos financeiros (faturamento, pagamentos, folha de pagamento, contabilidade) onde a precisão é crítica.

    Razões:

    • as operações financeiras são legalmente obrigadas a serem precisas até a menor unidade (como centavos), e o BigDecimal fornece essa precisão.
    • Os padrões contábeis exigem alta precisão e erros de arredondamento podem levar a problemas de conformidade.

    Duplo: Use para cálculos não financeiros, processamento de dados em grande escala e seções críticas de desempenho onde uma leve perda de precisão é aceitável.

    A chave aqui é usar BigDecimal quando os números afetam diretamente os resultados financeiros e Double ao trabalhar com grandes conjuntos de dados onde o desempenho é crítico e uma leve perda de precisão é tolerável.

    • -2

relate perguntas

  • Lock Condition.notify está lançando java.lang.IllegalMonitorStateException

  • Resposta de microsserviço Muitos para Um não aparece no carteiro

  • Validação personalizada do SpringBoot Bean

  • Os soquetes Java são FIFO?

  • Por que não é possível / desencorajado definir um lado do servidor de tempo limite de solicitação?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve