Arredondamento ABNT (SAT)
Moderador: Moderadores
- luiz53
- Usuário Nível 1

- Mensagens: 34
- Registrado em: 01 Jun 2007 14:23
- Localização: Santa fe do Sul - SP
Arredondamento ABNT (SAT)
Alguém fez a função de arredondamento ABNT 
HARBOUR + FIVEWIN + ADS SERVER + MYSQL + POSTGRES + Tdolphin
-
Kapiaba
- Colaborador

- Mensagens: 1908
- Registrado em: 07 Dez 2012 16:14
- Localização: São Paulo
- Contato:
ARREDONDAMENTO ABNT (SAT)
http://www.projetoacbr.com.br/forum/top ... ento-abnt/
Código: Selecionar todos
FUNCTION Round_ABNT(nValor,nDecimais)
LOCAL nRetorno:=nValor, cDecimais:=SubStr(Str(nValor),At('.',Str(nValor))+1), nSubsequente:=nDecimais+1
if nDecimais<1
RETURN Int(nRetorno)
endif
if Len(cDecimais) <= nDecimais
RETURN nRetorno
endif
if SubStr(cDecimais,nSubsequente,1)>'5' .or. SubStr(cDecimais,nSubsequente,1)<'5' //Se a casa decimal SUBSEQUENTE for DIFERENTE de 5
nRetorno:=Round(nValor,nDecimais) //ARREDONDA
elseif SubStr(cDecimais,nSubsequente,1)=='5' //Se a casa decimal SUBSEQUENTE for IGUAL a 5
if Mod(Val(SubStr(cDecimais,nDecimais,1)),2) <> 0 //Se a casa decimal que será CONSERVADA, for IMPAR
nRetorno:=Round(nValor,nDecimais) //ARREDONDA
else //se a casa decimal que será CONSERVADA, for PAR
if Val(SubStr(cDecimais,nSubsequente+1,1)) > 0 //Se APÓS a casa decimal SUBSEQUENTE, houver ALGUM algarismo MAIOR que ZERO
nRetorno:=Round(nValor,nDecimais) //ARREDONDA
else //Se APÓS a casa decimal SUBSEQUENTE, não houver NENHUM outro algarismo ou TODOS forem iguais a ZERO
nRetorno:=Truncate(nValor,nDecimais) //TRUNCA (Esse é o único momento em que o "arredondamento ABNT" se diferencia do "arredondamento normal")
endif
endif
endif
RETURN nRetorno
FUNCTION Truncate(nValor,nDecimais)
LOCAL nRetorno:=nValor, cDecimais:=SubStr(Str(nValor),At('.',Str(nValor))+1)
if nDecimais<1
RETURN Int(nRetorno)
endif
if Len(cDecimais) <= nDecimais
RETURN nRetorno
endif
nRetorno:=Val( Str(Int(nValor))+'.'+SubStr(cDecimais,1,nDecimais) )
RETURN nRetorno
- luiz53
- Usuário Nível 1

- Mensagens: 34
- Registrado em: 01 Jun 2007 14:23
- Localização: Santa fe do Sul - SP
ARREDONDAMENTO ABNT (SAT)
Como sempre o Kapiada é muito prestativo, Obrigado ...
Fiz um teste com essa rotina e com a minha que havia feito e ambas estão truncando o valor desse calculo. :
0.299 x 8.98 = 2,68502 (2.68)
só que no SAT o valor aceito é de 2.69
Minha rotina de Arredondamento :
Fiz um teste com essa rotina e com a minha que havia feito e ambas estão truncando o valor desse calculo. :
0.299 x 8.98 = 2,68502 (2.68)
só que no SAT o valor aceito é de 2.69
Minha rotina de Arredondamento :
Código: Selecionar todos
*******************************************************************************
FUNCTION NewROUND(f_val,f_dec)
*******************************************************************************
local dig18
local dig19
local dig20
local valor
default f_dec := 2
if valtype(f_val) # "N"
return f_val
endif
valor := str(f_val,20,4)
if right(valor,2) != '00'
dig18 := substr(valor,18,1)
dig19 := substr(valor,19,1)
dig20 := substr(valor,20,1)
if dig19 == '5' .and. isPar(val(dig18))
if dig20 == '0'
valor := str(xround(f_val,f_dec),20,f_dec)
else
valor := str( round(f_val,f_dec),20,f_dec)
endif
else
valor := str( round(f_val,f_dec),20,f_dec)
endif
endif
return val(valor)
*******************************************************************************
FUNCTION isPar(VALOR)
*******************************************************************************
RETURN if( valor % 2 == 0,.t.,.f.)
HARBOUR + FIVEWIN + ADS SERVER + MYSQL + POSTGRES + Tdolphin
-
Kapiaba
- Colaborador

- Mensagens: 1908
- Registrado em: 07 Dez 2012 16:14
- Localização: São Paulo
- Contato:
ARREDONDAMENTO ABNT (SAT)
Código: Selecionar todos
#include "FiveWin.ch" // I LOVE THIS
static oWnd
#xtranslate round(<nVal>,<nDec>) => val(str(<nVal>,20,<nDec>))
FUNCTION Main()
local oBar
DEFINE WINDOW oWnd TITLE "TestE Round() Harbour and xHarbour: Perfect!"
DEFINE BUTTONBAR oBar _3D OF oWnd
DEFINE BUTTON OF oBar ACTION Test_Round()
SET MESSAGE OF oWnd TO "TestE Round()" NOINSET CLOCK DATE KEYBOARD
ACTIVATE WINDOW oWnd
RETURN NIL
FUNCTION Test_Round()
LOCAL nImp, qt, preco, nNewImp, nNewValor
nNewValor := 0
nImp := 0.00
qt := 0.299
preco := 8.98
//nImp := Round( (qt * preco) , 2 )
nImp := ( ROUND( qt, 2 ) ) * ( ROUND( preco, 2 ) )
? ROUND( nImp, 2 )
? Str( Round( nImp, 2 ), 12, 6 ) // veja como apresenta aqui
nImp := Round(Val(StrZero(preco*qt,12,2)),4)
? ROUND( nImp, 2)
nNewImp := PADR( nImp, 6 )
nImp := VAL( PADR( nNewImp, 6 ) )
nNewValor := ROUND( nImp, 2 )
? nNewValor // assim retorna correto
RETURN NIL
Arredondamento ABNT (SAT)
Olá,
Temos estas funções em C, não sei se vai lhe atender
Temos estas funções em C, não sei se vai lhe atender
Código: Selecionar todos
#include "extend.api"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#define SOMA 0
#define SUBTRACAO 1
#define MULTIPLICACAO 2
#define DIVISAO 3
#define PRECISAO 20
double par1, par2;
int decimal;
char result[21];
void do_oper(int oper)
{double r1, err;
int dec, sig, aux;
char err_c[PRECISAO+1];
strcpy(err_c, "0.");
aux = decimal;
while(aux != 0)
{strcat(err_c, "0");
aux--;
}
strcat(err_c, "1");
err = atof(err_c);
switch(oper)
{case SOMA:
r1 = par1 + par2;
break;
case SUBTRACAO:
r1 = par1 - par2;
break;
case MULTIPLICACAO:
r1 = (par1 * par2);
break;
case DIVISAO:
r1 = (par1 / par2);
break;
}
if(r1 > 0)
r1 += err;
else
r1 -= err;
strcpy(result, ecvt(r1, PRECISAO, &dec, &sig));
if(dec<1)
{char ret[PRECISAO+1];
if( ((sig!=0)&&(dec<2-PRECISAO)) || ((sig==0)&&(dec<1-PRECISAO)) || (dec<=-(decimal)) )
{strcpy(ret, "0.");
if(decimal>0)
{aux = decimal;
while(aux>0)
{strcat(ret, "0");
aux--;}
}
strcpy(result, ret);
}
else
{strcpy(ret, "0.");
aux = dec;
while(aux<0)
{strcat(ret, "0");
aux++;
}
strncat(ret, result, decimal+dec);
strcpy(result, ret);
if(sig!=0)
{strcpy(ret, "-");
strncat(ret, result, PRECISAO-1);
strcpy(result, ret);
}
}
}
else
{if( ((sig==0)&&(dec>PRECISAO)) || ((sig!=0)&&(dec>PRECISAO-1)) )
{strcpy(result, "*");
aux = PRECISAO-1;
while(aux>0)
{strcat(result, "*");
aux--;
}
}
else
{char ret1[PRECISAO+1], ret2[PRECISAO+1];
strcpy(ret1, "");
strncat(ret1, result, dec);
if((sig==0)&&(dec>(PRECISAO-2)) || ((sig!=0)&&(dec>(PRECISAO-3))))
strcpy(result, ret1);
else
{strcat(ret1, ".");
strcpy(ret2, " ");
strncat(ret2, result, PRECISAO-1);
memmove(ret2, ret1, dec+1);
strcpy(result, "");
strncat(result, ret2, dec+1+decimal);
}
if(sig!=0)
{strcpy(ret1, "-");
strncat(ret1, result, PRECISAO-1);
strcpy(result, ret1);
}
}
}
return;
}
HB_FUNC (C_SUM)
{if(HB_ISCHAR(1))
par1 = atof(_parc(1));
else
par1 = _parnd(1);
if(HB_ISCHAR(2))
par2 = atof(_parc(2));
else
par2 = _parnd(2);
if(PCOUNT == 3)
{decimal = _parni(3);
if(decimal > 10)
decimal = 10;
else if(decimal < 0)
decimal = 0;
}
else
decimal = 2;
do_oper(SOMA);
_retc(result);}
HB_FUNC (C_SUB)
{if(HB_ISCHAR(1))
par1 = atof(_parc(1));
else
par1 = _parnd(1);
if(HB_ISCHAR(2))
par2 = atof(_parc(2));
else
par2 = _parnd(2);
if(PCOUNT == 3)
{decimal = _parni(3);
if(decimal > 10)
decimal = 10;
else if(decimal < 0)
decimal = 0;
}
else
decimal = 2;
do_oper(SUBTRACAO);
_retc(result);}
HB_FUNC (C_MULT)
{if(HB_ISCHAR(1))
par1 = atof(_parc(1));
else
par1 = _parnd(1);
if(HB_ISCHAR(2))
par2 = atof(_parc(2));
else
par2 = _parnd(2);
if(PCOUNT == 3)
{decimal = _parni(3);
if(decimal > 10)
decimal = 10;
else if(decimal < 0)
decimal = 0;
}
else
decimal = 2;
do_oper(MULTIPLICACAO);
_retc(result);}
HB_FUNC ( C_DIV )
{if(HB_ISCHAR(1))
par1 = atof(_parc(1));
else
par1 = _parnd(1);
if(HB_ISCHAR(2))
par2 = atof(_parc(2));
else
par2 = _parnd(2);
if(par2==0)
{printf("Erro de divisao por zero!");
exit(0);
}
else
{if(PCOUNT == 3)
{decimal = _parni(3);
if(decimal > 10)
decimal = 10;
else if(decimal < 0)
decimal = 0;
}
else
decimal = 2;
do_oper(DIVISAO);
_retc(result);
}
}
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
- Jairo Maia
- Moderador
- Mensagens: 2785
- Registrado em: 16 Ago 2010 13:46
- Localização: Campinas-SP
Arredondamento ABNT (SAT)
Olá Pessoal,
O SAT trabalha com as duas formas: Arredondamento e Truncamento.
Para Combustíveis, a tag indRegra no grupo do produto deve ser T, e o truncamento com 3 casas. Para todos os demais produtos a tag indRegra será A e o arredondamento com 2 casas. Para isso basta como já foi dito usar: Round( ( nValorUnitario X nQuantidade ), 2 ).
O SAT trabalha com as duas formas: Arredondamento e Truncamento.
Para Combustíveis, a tag indRegra no grupo do produto deve ser T, e o truncamento com 3 casas. Para todos os demais produtos a tag indRegra será A e o arredondamento com 2 casas. Para isso basta como já foi dito usar: Round( ( nValorUnitario X nQuantidade ), 2 ).
Abraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
- luiz53
- Usuário Nível 1

- Mensagens: 34
- Registrado em: 01 Jun 2007 14:23
- Localização: Santa fe do Sul - SP
Arredondamento ABNT (SAT)
OBRIGADO PELA AJUDA A TODOS....
JAIRO
O produtos que estou vendendo é PRODUTO de AÇOUGUE, feirinha COM 3 casas decimais APENAS NAS QUANTIDADE ( indRegra = 'A' )
SÓ que se uso o arredondamento ABNT para este valor 0.299 x 8.98 = (2,68 ABNT) mas o SAT ACEITA APENAS 2.69
entendeu
?
JAIRO
O produtos que estou vendendo é PRODUTO de AÇOUGUE, feirinha COM 3 casas decimais APENAS NAS QUANTIDADE ( indRegra = 'A' )
SÓ que se uso o arredondamento ABNT para este valor 0.299 x 8.98 = (2,68 ABNT) mas o SAT ACEITA APENAS 2.69
entendeu
HARBOUR + FIVEWIN + ADS SERVER + MYSQL + POSTGRES + Tdolphin
- Jairo Maia
- Moderador
- Mensagens: 2785
- Registrado em: 16 Ago 2010 13:46
- Localização: Campinas-SP
Arredondamento ABNT (SAT)
Olá Luiz,
Penso que entendi, mas acho que há confusão ai. Pela ABNT, arredondamentos entre 0 a 4 arredonda para baixo, 5 a 9 arredonda para cima. Exatamente isso que essa função faz: Round( ( nValorUnitario X nQuantidade ), 2 ):
Penso que entendi, mas acho que há confusão ai. Pela ABNT, arredondamentos entre 0 a 4 arredonda para baixo, 5 a 9 arredonda para cima. Exatamente isso que essa função faz: Round( ( nValorUnitario X nQuantidade ), 2 ):
Código: Selecionar todos
Function Main()
Local nValorItem := 0.299
Local nQuantidade := 8.98
? Round( ( nValorItem * nQuantidade ), 2 ) // retorna 2.69
Return NilAbraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
- luiz53
- Usuário Nível 1

- Mensagens: 34
- Registrado em: 01 Jun 2007 14:23
- Localização: Santa fe do Sul - SP
Arredondamento ABNT (SAT)
Jairo muito Obrigado pela atenção...
Conversei com a DIMEP e consegui a solução....
Usando a função do KAPIABA apenas com uma alterção

Conversei com a DIMEP e consegui a solução....
Usando a função do KAPIABA apenas com uma alterção
Código: Selecionar todos
*******************************************************************************
FUNCTION Round_ABNT(nValor,nDecimais)
*******************************************************************************
LOCAL nRetorno := nValor
LOCAL cDecimais := SubStr(Str(nValor),At('.',Str(nValor))+1)
LOCAL nSubsequente:= nDecimais+1
if nDecimais<1
RETURN Int(nRetorno)
endif
if Len(cDecimais) <= nDecimais
RETURN nRetorno
endif
if SubStr(cDecimais,nSubsequente,1)>'5' .or. SubStr(cDecimais,nSubsequente,1)<'5' //Se a casa decimal SUBSEQUENTE for DIFERENTE de 5
nRetorno:=nRound(nValor,nDecimais) //ARREDONDA
elseif SubStr(cDecimais,nSubsequente,1)=='5' //Se a casa decimal SUBSEQUENTE for IGUAL a 5
if Mod(Val(SubStr(cDecimais,nDecimais,1)),2) <> 0 //Se a casa decimal que será CONSERVADA, for IMPAR
nRetorno:=nRound(nValor,nDecimais) //ARREDONDA
else
// if Val(SubStr(cDecimais,nSubsequente+1,1)) > 0 //Se APÓS a casa decimal SUBSEQUENTE, houver ALGUM algarismo MAIOR que ZERO
if Val(SubStr(cDecimais,nSubsequente+1)) > 0 //Se APÓS a casa decimal SUBSEQUENTE, houver ALGUM algarismo MAIOR que ZERO
nRetorno:=nRound(nValor,nDecimais) //ARREDONDA
else //Se APÓS a casa decimal SUBSEQUENTE, não houver NENHUM outro algarismo ou TODOS forem iguais a ZERO
nRetorno:=Truncate(nValor,nDecimais) //TRUNCA (Esse é o único momento em que o "arredondamento ABNT" se diferencia do "arredondamento normal")
endif
endif
endif
RETURN nRetorno

HARBOUR + FIVEWIN + ADS SERVER + MYSQL + POSTGRES + Tdolphin
- Jairo Maia
- Moderador
- Mensagens: 2785
- Registrado em: 16 Ago 2010 13:46
- Localização: Campinas-SP
Arredondamento ABNT (SAT)
Olá Luiz,
Permita-me um pouco mais nesse assunto, pois é interessante.
Na figura que você postou, na célula 3, valia na normatização ABNT de 1977. Ocorre que para compatibilidade com a realidade de computadores, foi alterada pela ABNT a norma de Arredondamento em dezembro de 2014, com vigor a partir de janeiro 2015, já que era a realidade principalmente em planilhas.
Assim, na nova normatização se arredondar 4,885000 será 4,89, pois o ultimo digito após o digito verificador 8 é 5.
Permita-me um pouco mais nesse assunto, pois é interessante.
Na figura que você postou, na célula 3, valia na normatização ABNT de 1977. Ocorre que para compatibilidade com a realidade de computadores, foi alterada pela ABNT a norma de Arredondamento em dezembro de 2014, com vigor a partir de janeiro 2015, já que era a realidade principalmente em planilhas.
Assim, na nova normatização se arredondar 4,885000 será 4,89, pois o ultimo digito após o digito verificador 8 é 5.
Abraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
- luiz53
- Usuário Nível 1

- Mensagens: 34
- Registrado em: 01 Jun 2007 14:23
- Localização: Santa fe do Sul - SP
Arredondamento ABNT (SAT)
Agradeço pela ajuda...
VOU FAZER UM TESTE NO SAT para verificar essa possibilidade...
ai EU POSTO aqui o RESULTADO....
VOU FAZER UM TESTE NO SAT para verificar essa possibilidade...
ai EU POSTO aqui o RESULTADO....
HARBOUR + FIVEWIN + ADS SERVER + MYSQL + POSTGRES + Tdolphin
- luiz53
- Usuário Nível 1

- Mensagens: 34
- Registrado em: 01 Jun 2007 14:23
- Localização: Santa fe do Sul - SP
Arredondamento ABNT (SAT)
Jairo...
Acabei de fazer TESTE NO SAT DIMEP - ELGIN - KRYPTUS...
todos eles fizeram o arredondamento ABNT igual esta na IMAGEM..
EXEMPLO 3
4.885000 - ficou 4.88

Acabei de fazer TESTE NO SAT DIMEP - ELGIN - KRYPTUS...
todos eles fizeram o arredondamento ABNT igual esta na IMAGEM..
EXEMPLO 3
4.885000 - ficou 4.88

HARBOUR + FIVEWIN + ADS SERVER + MYSQL + POSTGRES + Tdolphin
Arredondamento ABNT (SAT)
Essa regra de arredondamento é muito esquisita, enfim no brasil as coisas são estranhas mesmo.
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
- Jairo Maia
- Moderador
- Mensagens: 2785
- Registrado em: 16 Ago 2010 13:46
- Localização: Campinas-SP
Arredondamento ABNT (SAT)
Olá Pessoal,
Quando você monta o XML, é seu sistema que arredonda ou trunca os valores, e envia para o SAT. Então o SAT verifica conforme o Schema.
Você usa o ACBrMonitor ou seu módulo para emissão do SAT é próprio?
rs... Pois é. Em se tratando de aplicativo fiscal então nem se fala...asimoes escreveu:Essa regra de arredondamento é muito esquisita, enfim no brasil as coisas são estranhas mesmo.
Não entendi essa parte. o SAT não faz arredondamento nenhum, ele apenas verifica se os valores da soma dos itens estão corretos com o valor total do cupom, e se a forma de pagamento foi com valor igual ou superior a soma do cupom.luiz53 escreveu:todos eles fizeram o arredondamento ABNT igual esta na IMAGEM..
Quando você monta o XML, é seu sistema que arredonda ou trunca os valores, e envia para o SAT. Então o SAT verifica conforme o Schema.
Você usa o ACBrMonitor ou seu módulo para emissão do SAT é próprio?
Abraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
- luiz53
- Usuário Nível 1

- Mensagens: 34
- Registrado em: 01 Jun 2007 14:23
- Localização: Santa fe do Sul - SP
Arredondamento ABNT (SAT)
JAIRO
Nao uso ACBR ... uso UMA CLASSE PRÓPRIA.
Quis dizer que se eu usar o arredondamento ROUND( ) o valor a ser pago sera diferente do valor calculado pelo SCHEMA do SAT....
Nao uso ACBR ... uso UMA CLASSE PRÓPRIA.
Quis dizer que se eu usar o arredondamento ROUND( ) o valor a ser pago sera diferente do valor calculado pelo SCHEMA do SAT....
HARBOUR + FIVEWIN + ADS SERVER + MYSQL + POSTGRES + Tdolphin