Ir para conteúdo
  • Cadastre-se

dev botao

RoundABNT - ACBrUtil - Correção


  • Este tópico foi criado há 2900 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

Nunca mandei nada para correção, então não sei como fazer isso, gostaria que se tiver uma forma melhor de fazer que me notifiquem.

Na função do RoundABNT, na verificação das regras 2.3 e 2.4 ( regra do par ou ímpar), era observado o valor errado para verificar se o mesmo era par ou ímpar.
Regras:

Citar

 

  2.3 Quando o algarismo imediatamente seguinte ao último algarismo a ser conservado
  for 5 seguido de zeros, dever-se-á arredondar o algarismo a ser conservado para
  o algarismo par mais próximo. Consequentemente, o último a ser retirado, se for ímpar,
  aumentará uma unidade.

  > Exemplo: 4,550 0 arredondados à primeira decimal tornar-se-ão: 4,6.


  2.4 Quando o algarismo imediatamente seguinte ao último a ser conservado
  for 5 seguido de zeros, se for par o algarismo a ser conservado, ele permanecerá sem modificação.

  > Exemplo: 4,850 0 arredondados à primeira decimal tornar-se-ão: 4,8.

Número a verificar: N
Número que estava sendo verificado: N

 


function RoundABNT(const AValue: Double; const Digits: SmallInt): Double;
var
   Pow, PowValue, RestPart, FracValue : Extended;
   IntCalc, FracCalc, LastNumber, IntValue : Int64;
Begin
   Pow       := intpower(10, abs(Digits) );
   PowValue  := AValue / 10 ;
   IntValue  := trunc(PowValue);
   FracValue := frac(PowValue);

   PowValue := SimpleRoundTo( FracValue * 10 * Pow, -9) ; // SimpleRoundTo elimina dizimas ;
   IntCalc  := trunc( PowValue );
   FracCalc := trunc( frac( PowValue ) * 100);

   if (FracCalc > 50) then
      Inc( IntCalc )

   else if (FracCalc = 50) then
    begin
      LastNumber := trunc( frac( IntCalc / 100) * 10);

      if odd(LastNumber) then
         Inc( IntCalc )
      else
       begin
         RestPart := frac( PowValue * 10 ) ;

         if RestPart > 0 then
            Inc( IntCalc );
       end ;
    end ;

   Result := ((IntValue*10) + (IntCalc / Pow));
end;

Alterada a linha:

Citar

LastNumber := round( frac( IntCalc / 10) * 10);

 


Na variável LastNumber era salvo o ultimo número a ser considerado e na verdade era pra ser salvo o ultimo número anterior a ele.
A regra realmente é confusa, mas (infelizmente) existe e temos que segui-la.

Editado por Anthero Vieria Neto
Link para o comentário
Compartilhar em outros sites

  • Fundadores

Até onde sei.. não há nada de errado com o RoundABNT.... veja os testes que são executados contra ele, nas Unit Testes do projeto...

Favor providenciar alguns valores que comprovem a sua tese...

Podemos usar o Emulador de ECF Bematech MP4200-TH-FI, para comprovar os resultados esperados

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

1 hora atrás, Daniel Simoes disse:

Até onde sei.. não há nada de errado com o RoundABNT.... veja os testes que são executados contra ele, nas Unit Testes do projeto...

Favor providenciar alguns valores que comprovem a sua tese...

Podemos usar o Emulador de ECF Bematech MP4200-TH-FI, para comprovar os resultados esperados

Eu executei justamente com esse emulador, e claramente a regra no calculo dele está errado, pois ele verifica sempre o número 5, nos testes da regra do par ou ímpar.

Refazendo os testes usando os números do exemplo da regra: 4,550 e 4,850:

RoundABNT( 4.855, 3 ); => Resultado: 4,86  Regra ABNT: 4,85
RoundABNT( 4.555, 3 ); => Resultado: 4,86  Regra ABNT: 4,86

o Emulador da MP4200-TH-FI exibe os resultados coerentes com a regra, porém o RoundABNT não.
Amanhã cedo irei editar, anexando imagens com testes informados e a unit com as alterações.

Link para o comentário
Compartilhar em outros sites

  • Fundadores

RoundABNT( 4.855, 3 ); => 4.855 

Não há arredondamento... você informou 3 casas, e pediu para arredondar na 3 casa...

Tente com:

RoundABNT( 4.855, 2 )

Conferiu os fontes da UnitTest ?  Confira em: ACBr\Testes\FPCUnit\ACBrComum\acbrutiltest.pas

procedure RoundABNTTest.TresParaDuasCasasDecimais;
begin
  CheckEquals( 5.10, RoundABNT(5.101, 2));
  CheckEquals( 5.10, RoundABNT(5.102, 2));
  CheckEquals( 5.10, RoundABNT(5.103, 2));
  CheckEquals( 5.10, RoundABNT(5.104, 2));
  CheckEquals( 5.10, RoundABNT(5.105, 2));
  CheckEquals( 5.11, RoundABNT(5.1050123, 2));
  CheckEquals( 5.11, RoundABNT(5.106, 2));
  CheckEquals( 5.11, RoundABNT(5.107, 2));
  CheckEquals( 5.11, RoundABNT(5.108, 2));
  CheckEquals( 5.11, RoundABNT(5.109, 2));
end;

 

  • Curtir 2
Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

9 horas atrás, Daniel Simoes disse:

RoundABNT( 4.855, 3 ); => 4.855 

Não há arredondamento... você informou 3 casas, e pediu para arredondar na 3 casa...

Tente com:

RoundABNT( 4.855, 2 )

Conferiu os fontes da UnitTest ?  Confira em: ACBr\Testes\FPCUnit\ACBrComum\acbrutiltest.pas


procedure RoundABNTTest.TresParaDuasCasasDecimais;
begin
  CheckEquals( 5.10, RoundABNT(5.101, 2));
  CheckEquals( 5.10, RoundABNT(5.102, 2));
  CheckEquals( 5.10, RoundABNT(5.103, 2));
  CheckEquals( 5.10, RoundABNT(5.104, 2));
  CheckEquals( 5.10, RoundABNT(5.105, 2));
  CheckEquals( 5.11, RoundABNT(5.1050123, 2));
  CheckEquals( 5.11, RoundABNT(5.106, 2));
  CheckEquals( 5.11, RoundABNT(5.107, 2));
  CheckEquals( 5.11, RoundABNT(5.108, 2));
  CheckEquals( 5.11, RoundABNT(5.109, 2));
end;

Foi um erro de digitação, mo eu sistema está com 2 digitos,

Segue Programa teste e .pas alterado.

Verifique os valores do exempo, 4,855 e 4,555.
Quando for par deve ficar 4,X5
Quando for ímpar: 4,X6.

Obrigado pela atenção 

 

ACBrUtil.pas

Teste ACBr Util.zip

Link para o comentário
Compartilhar em outros sites

21 minutos atrás, Anthero Vieria Neto disse:

Foi um erro de digitação, mo eu sistema está com 2 digitos,

Segue Programa teste e .pas alterado.

Verifique os valores do exempo, 4,855 e 4,555.
Quando for par deve ficar 4,X5
Quando for ímpar: 4,X6.

Obrigado pela atenção 

 

ACBrUtil.pas

Teste ACBr Util.zip

Arquivos enviados incorretos... reenviando-os

Teste ACBr Util.zip

ACBrUtil.pas

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Você realmente testou esses valores contra o emulador da Bematech ?? Veja:

IMPRESSORA FISCAL BEMATECH MP-4200 TH FI
      APENAS PARA DESENVOLVIMENTO
            SEM VALOR FISCAL
CNPJ: 82.373.077/0001-71 IM: ISENTO
------------------------------------------------
02/02/2016 17:18:59  CCF:000000003 COO:000000010
CUPOM FISCAL
ITEM CÓDIGO DESCRIÇÃO QTD. UN. VL UNIT(R$) ST VL ITEM(R$)
------------------------------------------------
001 111222333 TESTE DE PRODUTO 4,855 UNX1,00 N1            4,86
002 111222333 TESTE DE PRODUTO 4,555 UNX1,00 N1            4,56

 

O RoundABNT reproduz o mesmo resultado...

procedure RoundABNTTest.TresParaDuasCasasDecimais;
begin
  CheckEquals( 4.86, RoundABNT(4.855, 2));
  CheckEquals( 4.56, RoundABNT(4.555, 2));   

Esse site explica a regra em detalhes:
http://www.sofazquemsabe.com/2011/01/como-fazer-arredondamento-da-numeracao.html

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

3 horas atrás, Daniel Simoes disse:

Você realmente testou esses valores contra o emulador da Bematech ?? Veja:


IMPRESSORA FISCAL BEMATECH MP-4200 TH FI
      APENAS PARA DESENVOLVIMENTO
            SEM VALOR FISCAL
CNPJ: 82.373.077/0001-71 IM: ISENTO
------------------------------------------------
02/02/2016 17:18:59  CCF:000000003 COO:000000010
CUPOM FISCAL
ITEM CÓDIGO DESCRIÇÃO QTD. UN. VL UNIT(R$) ST VL ITEM(R$)
------------------------------------------------
001 111222333 TESTE DE PRODUTO 4,855 UNX1,00 N1            4,86
002 111222333 TESTE DE PRODUTO 4,555 UNX1,00 N1            4,56

 

O RoundABNT reproduz o mesmo resultado...


procedure RoundABNTTest.TresParaDuasCasasDecimais;
begin
  CheckEquals( 4.86, RoundABNT(4.855, 2));
  CheckEquals( 4.56, RoundABNT(4.555, 2));   

Esse site explica a regra em detalhes:
http://www.sofazquemsabe.com/2011/01/como-fazer-arredondamento-da-numeracao.html

 

Exatamente, está errado! quando você colocar 4,555 o resultado tem que ser 4,56, mas quando colocar 4,855 o resultado tem que ser 4,85.

Editado por Anthero Vieria Neto
Link para o comentário
Compartilhar em outros sites

  • Fundadores

O ECF da Bematech está errado ???

OK... vamos testar em outro... Veja a conta do emulador da Sweda

S W E D A
Rua Dona Brígida, 713
Vila Mariana - São Paulo - SP
CNPJ: 53.485.215/0001-06
IE: 111.072.115.110
IM: 111.111.111.111
SIMULADOR SWEDA CONNECT/SIM
————————————————————————————————————————————————————————
02/02/2016  21:18:27  CCF:000017              COO:000051
          CUPOM FISCAL
ITEM CÓDIGO      DESCRIÇÃO
QTD.     UN.  VL UNIT(R$)     ST             VL ITEM(R$)
1 111222333 TESTE DE PRODUTO 1 UN x 4,855 N1       4,86
2 111222333 TESTE DE PRODUTO 1 UN x 4,555 N1       4,56

Sinceramente... dou esse tópico por encerrado...

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • 1 mês depois ...
  • Membros Pro

Sim , Daniel o roundABNT esta errado , o nosso amigo ai nao soube demonstrar o erro, aqui vai a demonstracao do erro

pegue o valor   qtde produto = 0,690 x 

                               valor       = 28,50   

                            total           =  19,665

portanto    na impressora fiscal pela regra abnt quando tem 3 casas para arredondar para 2,     e a ultima for 5 seguida de zeros

se o algarismo a ser arredondado for par (6¨e par) deve ficar como esta = 19,66

se for impar deve somar 1 ao algarismo a ser arredondado.

no roundABNT da acbr resulta em 19,67 ou seja esta ERRADO!.....Mr Daniel... 

 

 

Editado por geanjesus
Link para o comentário
Compartilhar em outros sites

  • Membros Pro

outro valor 

 qtde   =    0,25


valor  =     36,50


total   =     9,125

pelo roundABNT = 9,12   mantem o valor pela regra por ser par  e esta correto, pela regra...

qtde   = 0,110
 

valor  = 50,50


total   = 5,555

pelo roundABNT = 5,56  soma 1 pela regra por ser impar e esta correto , pela regra...

pelo que notei na rotina do acbr, ele so mantem o valor  do algarismo a ser 

arredondado
quando for par e for menor que 5, mas isto nao esta na regra do ABNT,

la diz somente, 
se for par o algarismo a ser arredondado deve permanecer como esta.
 

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Não viaja... o RoundABNT não resulta 19.67 e sim 19.66... antes de sair falando... use a UnitTeste

 

  dblValorUnit := 0.69;
  dblQtde := 28.50;
  dblTotal := dblValorUnit * dblQtde;
  CheckEquals( 19.66, RoundABNT(dblTotal, 2));    

 

Não responderei mais a esse tópico, a não ser que os "entendidos" façam testes usando a UnitTeste...

Não sabe usar a UnitTeste ?  então use o ECFTeste, e venda um item com os valores indicados, em um emulador de ECFs qualquer, pois eles seguem a regra de arredondamento do ABNT... (Use 3 casas na Qtd, se necessário (e não no Preço Unitário))

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • Membros Pro

bom Daniel, eu baixei agora a ultima versao do acbr e realmente foi alterada a funcao incluindo a constante delta, eu ja tinha feito algo semelhante para pode resolver por aqui, entao , mas foi a pouco tempo que eu tinha pego esta que eu tinha aqui..

valeu entao , a ultima agora deve estar estar correta, e eu sofri muito com esses arredondamentos super esporadicos por sinal

vou testar a sua agora com essas modificacoes e posto aqui novamente... 

A rotina que eu estava usando estava identica a que foi colocada no inicio do topico...

e a rotina atual que baixei hoje e essa...veja que sao diferentes...

function RoundABNT(const AValue: Double; const Digits: SmallInt; const Delta: Double):Double;
var
   Pow, FracValue, PowValue : Extended;
   RestPart: Double;
   IntCalc, FracCalc, LastNumber, IntValue : Int64;
   Negativo: Boolean;
Begin
   Negativo  := (AValue < 0);

   Pow       := intpower(10, abs(Digits) );
   PowValue  := abs(AValue) / 10 ;
   IntValue  := trunc(PowValue);
   FracValue := frac(PowValue);

   PowValue := SimpleRoundTo( FracValue * 10 * Pow, -9) ; // SimpleRoundTo elimina dizimas ;
   IntCalc  := trunc( PowValue );
   FracCalc := trunc( frac( PowValue ) * 100 );

   if (FracCalc > 50) then
     Inc( IntCalc )

   else if (FracCalc = 50) then
   begin
     LastNumber := round( frac( IntCalc / 10) * 10);

     if odd(LastNumber) then
       Inc( IntCalc )
     else
     begin
       RestPart := frac( PowValue * 10 ) ;

       if RestPart > Delta then
         Inc( IntCalc );
     end ;
   end ;

   Result := ((IntValue*10) + (IntCalc / Pow));
   if Negativo then
     Result := -Result;
end;
 

 

Link para o comentário
Compartilhar em outros sites

  • Membros Pro

Muito Obrigado, Mr.  Daniel , eu quase perdi um cliente por causa dessa rotina que eu estava usando, que era igual a do comeco do post e algumas vezes bem esporadico, dava erro no frente de loja com a impressora fiscal por causa de 0.01 centavo e por tudo que eu ja tinha feito e refeito e nada de descobrir, ai atraves de uma pesquisa aqui pelo forum vi que tinha essa rotina do abnt , entao comecei a usa-la, passava quase tudo menos isso que te relatei, agora com a ultima versao, finalmente acho que nao vou mais perder noites de sono com arredondamentos na impressora fiscal, inclusive serve para o sat tambem...ja vi aqui...  

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Obrigado pelo retorno...

Eu aconselho a dar uma estudada nos testes unitários que estamos desenvolvendo para o ACBr...

Com eles é praticamente impossível, deixar algo errado passar... a título de exemplo, somente para a RoundABNT, são aplicados mais de 200 testes diferentes...

 

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • 4 semanas depois ...

Boa tarde!!

Ao registrar um produto com desconto no item anterior ACBrSAT, passando pela unit ACBrEcfVirtual.pas procedure DescontoAcrescimoItemAnterior, o valor de desconto quando em % é convertido para negativo, e passado para função roundABNT

O estranho é que quando esse valor é negativo o retorno da função sempre traz -0,01 centavos, fiz os testes com RoundTo e nao obtive essa diferença.

Exemplo

RoundABNT( -4.00, -2 ) = -3.99   ja utilizando RoundTo( -4.00, -2 ) = -4.00

Mais um Exemplo abaixo

RoundABNT( -1.34, -2 ) = -1.33   ja utilizando RoundTo( -1.34, -2 ) = -1.34

Quem puder ajudar nessa correção, não conseguimos identificar esse erro.

Obrigado

 

 

Editado por Fabio Farias
Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois ...
  • Este tópico foi criado há 2900 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.