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 / dba / Perguntas / 333275
Accepted
Daviid
Daviid
Asked: 2023-11-20 16:59:01 +0800 CST2023-11-20 16:59:01 +0800 CST 2023-11-20 16:59:01 +0800 CST

Soma da Rodada vs Rodada da Soma

  • 772

Esta é uma pequena amostra do que tenho em meu banco de dados.

CREATE TEMPORARY TABLE temp_ledger(
    book_entry INT,
    credit DOUBLE(24, 8),
    debit DOUBLE(24, 8)
);

INSERT INTO
    temp_ledger(book_entry, credit, debit)
VALUES
    (1, 17.54500000, 0.00000000),
    (1, 0.00000000, 14.50000000),
    (1, 0.00000000, 3.04500000),
    (2, 0.00000000, 99.85500000),
    (2, 95.10000000, 0.00000000),
    (2, 4.75500000, 0.00000000);

SELECT
    book_entry,
    SUM(ROUND(debit, 2)) as sum_of_rounded_debit,
    SUM(ROUND(credit, 2)) as sum_of_rounded_credit,
    ROUND(SUM(debit), 2) as round_of_summed_debit,
    ROUND(SUM(credit), 2) as round_of_summed_credit,
    SUM(debit) as summed_debit,
    SUM(credit) as summed_credit
FROM
    temp_ledger
GROUP BY
    book_entry;

DROP TEMPORARY TABLE temp_ledger;

Saída

temp_ledger

entrada_livro soma_de_débito_arredondado soma_de_crédito_arredondado round_of_summed_debit round_of_summed_credit débito_somado crédito_sumado
1 17,54 17,55 17,55 17,55 17.54500000 17.54500000
2 99,86 99,86 99,86 99,85 99.85500000 99.85500000

Não entendo por que sum_of_rounded_debita entrada do livro 1 é 17,54 :

  • 14,50 arredondado deve ser 14,50
  • 3,045 arredondado deve ser 3,05

E round_of_summed_creditpara o lançamento contábil 2 é 99,85 se summed_credit for 99,855 , por que o arredondamento me dá 99,85 e não 99,86

Eu entendo que às vezes os decimais podem ser complicados, mas round_of_summed_creditem particular me pergunto "O quê?".

Isso surgiu ao tentar encontrar erros na tabela llx_accounting_bookkeeping de Dolibarr, uma vez que a soma da rodada fornece algumas linhas como incompatíveis entre crédito e débito, enquanto a soma da rodada fornece um conjunto diferente de linhas.

Usando MariaDB 10.5.8

mariadb
  • 1 1 respostas
  • 23 Views

1 respostas

  • Voted
  1. Best Answer
    bobflux
    2023-11-20T17:58:08+08:002023-11-20T17:58:08+08:00

    Os números de ponto flutuante funcionam na base 2, portanto a conversão de e para a base 10 sempre introduz pequenos erros. Quando eles são convertidos para base 10 para exibição, isso é (um pouco e geralmente, mas nem sempre) oculto pelo arredondamento para menos que o número total de dígitos... mas se você espera que o ponto flutuante seja exato, não funcionará.

    Por exemplo, o número "3.045" não pode ser codificado como precisão dupla de ponto flutuante, portanto, a representação mais próxima disponível é usada:

    3.04499999999999992895

    Ao usar round() com número de decimais 2, ele é arredondado para:

    3.0400000000000003553

    Este resultado está correto, porque 3,044999... (que arredonda para 3,04) não é 3,045 (que arredonda para 3,05). O problema é que você acredita que converter 3,045 para ponto flutuante de precisão dupla dá um resultado igual a 3,045. Isso não.

    Python demonstra:

    >>> round(3.045,2)
    3.04
    

    A natureza não exata dos números flutuantes significa que eles nunca devem ser usados ​​para representar números exatos de base 10, especialmente no contexto da contabilidade.

    Felizmente este é um problema resolvido, pois seu banco de dados fornece um tipo exato de ponto fixo: Numeric/Decimal .

    Você pode especificar a precisão desses tipos decimais conforme desejar. Normalmente na contabilidade a menor unidade é o centavo, não é possível fazer transferência bancária ou cheque com centavos fracionários, portanto os números são especificados com precisão de 2 dígitos após a vírgula. Em outros contextos, como criptografia, onde um azarado proprietário de $ DOGE vende, você poderia ter uma transferência de 0,000002 BTC, então você pode querer adicionar mais dígitos.

    A questão toda é que o valor armazenado na tabela é a quantia exata de dinheiro que foi transferida na transação, e não uma conversão aproximada para float.

    Feito isso, todos os cálculos estarão corretos.

    Não tenho ideia do que sum(round()) deve alcançar. Se você quiser sum() de pagamentos, então você deve fazer sum() de pagamentos, e não arredondá-los antes de somar.

    Há uma explicação possível: os designers deste banco de dados usaram floats para contabilidade , o que significa que eles não têm ideia do que estão fazendo. Então eles usaram round() como uma tentativa de corrigir os erros introduzidos pelo uso do tipo de dados errado.

    Não vai funcionar. Você deve usar o tipo de dados correto ou seus resultados sempre estarão errados.

    Observe que, como os dados na tabela estão no tipo de dados errado, a conversão para Decimal pode apresentar problemas. Por exemplo, se o valor "3,045" (na verdade 3,04499999999999992895) estiver armazenado e você o converter para Decimal(8,2), verifique se ele fornece o resultado desejado.

    Como todo o aplicativo é escrito em php, e o php não tem tipo Decimal (apenas flutuantes)... a maneira usual de fazer isso em php é converter tudo em centavos e usar apenas números inteiros. Portanto, os cálculos feitos no aplicativo também podem estar errados . Os sintomas incluem somas calculadas em php diferentes das somas calculadas no banco de dados.

    • 1

relate perguntas

  • Erro de cabeçalho do MariaDB

  • Erro 1046 Mariadb: nenhum banco de dados selecionado

  • Você ainda usa o MyISAM ou prefere o mecanismo de armazenamento Aria?

  • Como posso melhorar minha instrução SQL com resultados semanais com semana começando na quinta-feira ou em qualquer outro dia da semana?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

Sidebar

Stats

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

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

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