Página 1 de 1

Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 12 Jun 2008 16:32
por Spitzer
Olá!

Pessoal, o texto ficará longo, mas por favor, leiam porque não consigo achar uma solução (solução tenho até mais de uma, mas preciso de uma que tome o menor tempo para ser processada).

Estou com um problema de lógica pura num programa Clipper.
Preciso desenvolver um RPA onde os encargos não são descontados do prestador de serviços, porque a empresa arca com estes encargos.
Mas, mesmo assim, a empresa quer que estes encargos sejam destacados no RPA como se descontados tivessem sido.
Então preciso ajustar para cima o valor contratado de forma que, ao aplicar os descontos, dê o valor líquido contratado.
É mais ou menos como utilizar a opção “Atingir Meta” do Excel.
Pensei numa regrinha de três jogando valores altos, e fictícios, para poder estabelecer a relação percentual entre o valor bruto (que eu devo encontrar) e o valor líquido (que é o valor contratado), mas já cheguei ao consenso que não é possível, pois o IR, por exemplo, só existirá após uma faixa de valor, então pode ser que o valor líquido contratado não atinja IR, mas que quando eu chegar ao valor bruto, atinja, assim como há descontos que obedecem a certo teto, como é o caso do INSS.
Incrementar de centavo a centavo até chegar ao valor bruto determinado, também fica inviável, pois a rotina de cálculos faz acessos à base de dados para buscar limites, atualizar cálculos cumulativos, buscar tetos, enfim, e incrementando os valores centavo a centavo, a rotina seria executada milhares de vezes e levaria muito tempo, tempo este que o prestador de serviços não aguardará.

Vou montar um pequeno exemplo para ficar mais claro tudo aí em cima:
VALOR BRUTO: 713,70
DESCONTOS: 3,57
INSS RETIDO: 15,70
ICMS – SUBSTITUIÇÃO: 68,51
VALOR LÍQUIDO: 625,92

Então, o valor que será passado ao programa será R$ 625,92, que é o que foi contratado com o prestador de serviços, e o programa deverá chegar aos 713,70.
Lógico que todo o cálculo estará num laço, mas este laço deverá ser executado o menor número de vezes possível, senão a performance degradará muito (já testei isto).

Bom, depois da longa história, vem a pergunta:
PELO AMOR DE DEUS, COMO SAIO DE UM VALOR LÍQUIDO PARA CHEGAR NUM VALOR BRUTO QUE DESCONHEÇO, ONDE O VALOR LÍQUIDO É O VALOR BRUTO MENOS OS ENCARGOS, DE FORMA QUE A ROTINA SEJA EXECUTADA NO MENOR NÚMERO DE VEZES POSSÍVEL?

Desde já, muito obrigado mesmo!


Abraços,
Ademir Spitzer

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 12 Jun 2008 22:11
por Manuel Luis Modernel
Meu amigo Spitzer !

Inicia tua regra de 3 fazendo com que o teu valor liquido (R$ 625,92) seja o 100% e o R$ 713,70 o resulatado final, o "X" da questão.

Sabes onde isso é feito e VC pode tirar uma duvida, nas contas de Luz onde a aliquota é 25% e se for ver eles cobram Juros sobre os próprios juros dando quase uma aliquota de 32 % e não 25%.

espero ter te ajudado !!

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 13 Jun 2008 03:23
por Spitzer
Olá, Manuel!

Obrigado pela resposta.

Com regra de três não é possível (creio eu!).
Acontece que haverá casos (e é fato real isto, pois já houve casos assim) que eu posso ter um certo valor contratado que se ele fosse a base final para o RPA, não haveria a incidência de IR.
Se não me engano, o valor que passa a ter incidência de IR é R$ 1.372,81.
Então imagine um valor contratado de R$ 1.350,00.
Quando eu for achar um valor bruto que, com o descontos ele dê R$ 1.350,00, este bruto terá então incidência de IR.
Quer dizer, há casos onde a relação percentual do bruto para o líquido é de 15%, por exemplo, mas há casos onde esta relação é 17%, 19%...
Os descontos não possuem um percentual fixo. E há descontos que dependendo do valor, podem ou não ocorrer.

EU FIZ ASSIM:
Sobre o valor contratado, digamos os R$ 625,92, já acrescento 10%, pois em nenhuma hipóstese os descontos serão inferiores a isto.
Isto eleva o valor a R$ 688,51.
Então chamo a rotina de cálculo passando 688,51 como parâmetro e verifico o valor líquido retornado.
O valor líquido retornado será inferior a 625,92.
Então aumento 0,01 (1 centavo) e chamo a rotina de cálculo novamente, passando, desta vez, 688,52.
O valor retornado é ainda inferior a 625,92.
Aí chamo a rotina novamente passando 688,53, depois, 688,54, depois 688,55... Até que eu chamo a rotina passando 713,70 como parâmetro e o valor líquido retornado é 625,92, que é o valor contratado (a ser efetivamente pago).
Só que isto tá levando uma eternidade! Mais de meia hora!
Se eu não tivesse acesso a base de dados, fossem só cálculos simples, estas mais de 2.500 vezes que a rotina é chamada por tentativa e erro, levaria menos de 5 segundos.
Então tenho que reduzir o número de chamadas para 15, talvez 20 vezes, no máximo.
Agora, como faço isto já que não há uma regra fixa?
Pois há impostos que são cumulativos e a partir de um certo valor que começa a calcular, outros, que dependendo do valor, pegam faixas diferentes de percentuais de descontos (como o IR, por exemplo, que possui a isenção, 15% ou 27,5% de desconto, e que ainda, se o valor for inferior a R$ 10,00, não se desconta nem recolhe), e outros ainda, que quando atingem um determinado teto, não se desconta mais, como o INSS, por exemplo.

É um saco ou não?

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 13 Jun 2008 06:56
por MARINI
Bom dia,
A fórmula é:

valor/((100-taxas)/100)

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 13 Jun 2008 10:24
por rochinha
Amiguinho

Use a formula acima, carregue os valores de limite e teto antes de entrar no laco, tipo:

Código: Selecionar todos

// Puxe Varlores Da Tabela INSS conforme seus campos
INSS_Limite0 := 0
INSS_Limite1 := 50
INSS_Limite2 := 150
INSS_Limite3 := 300
INSS_Limite4 := 450
...
do case
    case ( ValorQueQueroTestar > INSS_Limite0 .and. ValorQueQueroTestar <= INSS_Limite1 )
    ...
    case ( ValorQueQueroTestar > INSS_Limite1 .and. ValorQueQueroTestar <= INSS_Limite2 )
    ...
    case ( ValorQueQueroTestar > INSS_Limite2 .and. ValorQueQueroTestar <= INSS_Limite3 )
    ...
endcase
Use este esquema para cada tabela que voce possue e coloque o laco para usar este método, os acesso as tabelas serão reduzidos a nada.

Eu usei estes métodos em meu antigo sistema de cooperativas que produzia num unico dia cerca de 3000 holerits com calculos complexos e a maioria dos calculos existiam na tabela de eventos onde eu armazenava para cada evento as variaveis e seus calculos como codeblocks que eram avaliados no momento do uso da rotina de calculo, exemplos:

Código: Selecionar todos

EVENTO | DESCRICAO | TRIBUTAVEL | CODEBLOCK
999 | PRODUCAO BASE | S | M->QTDE:=0,M->VALOR:=M->SALARIO*IIF(M->IDSALARIO=10,M->DIAS,1)
81 | HORA EXTRA 50% | S | IIF(M->VLEXTRAS=0,M->BASEHORA * 1.5,M->VLEXTRAS)
82 | HORA EXTRA 100% | S | IIF(M->VLEXTRAS=0,M->BASEHORA * 2,M->VLEXTRAS)
77 | COMISSAO | N | M->COMISSAO
122 | D.S.R.SOBRE COMISSOES | S | DIV(M->COMISSAO,M->DIAS-M->FOLGAS)*(M->FOLGAS-(M->FALTAS+M->FOLGAS))
Minha tabela de eventos possui mais de 100 eventos e cada funcionario seria verificado 100 vezes para o calculo dos eventos lancados em seu holerit. Para reduzir isto, o holerit do mesmo era avaliado a partir de alguns eventos selecionados e armazenados em uma tabela de eventos por funcionario, diminuindo o laco para cda calculo.

Em suma, antes de iniciar a rotina de calculos eu levava o maximo de informações para a memória para evitar aberturas e fechamentos de tabelas, pois se um delas se corrompesse no meio do caminho, tudo tinha de ser refeito. Na verdade a rotina fazia a impressão do holerit, então imagine o problema.

Não use a cabeça, use a memória, do micro.

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 13 Jun 2008 11:15
por MARCELOG
Veja isso:

VALOR BRUTO: 713,70
DESCONTOS: 3,57
INSS RETIDO: 15,70
ICMS – SUBSTITUIÇÃO: 68,51
VALOR LÍQUIDO: 625,92

x := 0
nValorLiq := 700,00
nBruto:=nValorLiq

Do while .t.

Crie as regras para cálculo dos impostos (com as classes de rendimento) considerando o valor líquido como o bruto incial, colocando o resultado na variável x.
Para agilizar o processo aumente o valor inicial com o mínimo exigível, e/ou crie faixas mínimas conhecidas.
Ex:

Se o valor é 1.000, não dá menos de 1.500
Então nBruto é

nBruto := nBruto *1,5

Isso retira 50.000 loops (R$500,00 : R$0,01)

Inss
Icms
Ir/Fonte
Descontos

Agora x é igual ao líquido, então é só comparar.

if x # (nValorLiq-0,01) or x # (nValorLiq+0,01) // Admito uma diferencinha.
nBruto + 0,01
Loop
else
exit
endif

enddo

? nBruto

MarceloG

Ou então, use o processo binário.

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 13 Jun 2008 11:40
por MARCELOG
Não falei do processo binário né.

Simples... (rsrsrsrs)

Pegue o valor, multiplique o mesmo por dois e teste.
Ex:
Se o líquido é igual a 700 faça o teste com 1.400,00

Se o resultado final líquido é maior que o líquido desejado, faça o teste loop retirando centavos.

Caso contrário, faça o teste loop acrescentando centavos.

Isso garante metade do tempo de processamento e pode ser refinado, comparando e dividindo/ multiplicando por dois as diferenças verificadas de modo a reduzir ainda mais esse tempo.

MarceloG

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 13 Jun 2008 14:43
por Manuel Luis Modernel
OI Amigo Spitzer,

Já foi levantado aqui um caso similar onde "O Programador" tentava resolver o problema "do Contador" e é isto que está acontecendo contigo no meu ver, teu problema não é de Programação e sim de Matematica Financeira.

A opinião geral foi nestes moldes:
VC enquanto PROGRAMADOR não tem obrigação de saber todas as rotinas administrativas de uma empresa, e por este motivo nada melhor do que consultar a pessoa que vem fazendo estes CÁLCULOS NO BRAÇO a muito tempo.
Te garanto que a pessoa deve ter uma saida muito simples e correta, caso contrário não teria feito por tanto tempo na "Maquininha de Calcular".

Perguntar a quem faz e sabe não é VERGONHA, quando a gente esta programando nada melhor do que colocar um pouco de responsabilidade no usuário, fazer ele participar, opinar e até testar o que VC está fazendo(lógico quando isto é possível). É assim que um programa fica 100% correto na opinião do usuário e é esta pessoa que vai fazer tua Propaganda posto que ele participou e ajudou a faze-lo.

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 13 Jun 2008 17:42
por Spitzer
CONSEGUI! CONSEGUI! CONSEGUI!

Na solução que vou postar abaixo, em todos os testes que fiz, a função foi chamada, no máximo, apenas 10 vezes!
O resultado sai em poucos segundos (10, 12... 15, foi o máximo, nos testes que fiz).

Faço assim:
O primeiro cálculo chamo pelo valor contratado (que é o líquido, digamos, 625.92), considerando que este seria o valor bruto, ou seja, a minha base de cálculo.
Aí, do valor líquido que deu (548.93), apuro a diferença para o que deveria dar (os tais 625.92).
A primeira diferença é de 76.99.
Somo esta diferença ao valor da minha primeira tentativa (625.92 + 76.99), que dá 702.91.
Então, para a minha próxima tentativa, a base de cálculo será os tais 702.91.
Esta base de cálculo gera um líquido de 616.46, que para o líquido que deveria dar (625.92), dá uma diferença de 9.46.
Aí somo a minha segunda base de cálculo à diferença (702.91 + 9.46), e chego ao valor de 712.37.
E assim sucessivamente, até que o líquido que deu (625.92) é o líquido que realmente deveria dar (625.92), e minha última base de cálculo, o meu valor bruto, que é os tais 713.7.

Na coluna "Líquido que Deu", é o líquido que peguei depois que a função faz os cálculos e me retorna o valor líquido. Se alguém quiser destrinchar pelos meus exemplos que postei antes, pode ver que chegará certinho nos valores que estão na citada coluna!

Depois desta, considero que minha semana foi muito bem ganha!

Abaixo, as apurações no Excel para entenderem melhor.

Lembrando que no segundo exemplo, no primeiro cálculo, não incide IRRF, mas a partir do segundo cálculo, sim.
E no terceiro exemplo, no meio do cálculo, a faixa muda no meio do cálculo (de 15 para 27,5%).

Pessoal, muito obrigado pelas dicas e sugestões!

As apurações:

Código: Selecionar todos

Bruto: 713,70    Líquido: 625,92
Quant.de       Base de      Líquido      Líquido que
Tentativas     Cálculo      que Deu      Deveria Dar    Díferença
         1      625,92       548,93           625,92        76,99
         2      702,91       616,46           625,92         9,46
         3      712,37       624,76           625,92         1,16
         4      713,53       625,76           625,92         0,16
         5      713,69       625,91           625,92         0,01
         6      713,70       625,92           625,92          -

Bruto: 4.000,00    Líquido: 3.469,77
Quant.de       Base de      Líquido      Líquido que
Tentativas     Cálculo      que Deu      Deveria Dar    Díferença
         1      3.469,77   3.042,99         3.469,77       426,78
         2      3.896,55   3.384,91         3.469,77        84,86
         3      3.981,41   3.454,51         3.469,77        15,26
         4      3.996,67   3.467,04         3.469,77         2,73
         5      3.999,40   3.469,27         3.469,77         0,50
         6      3.999,90   3.469,69         3.469,77         0,08
         7      3.999,98   3.469,75         3.469,77         0,02
         8      4.000,00   3.469,77         3.469,77          -

Bruto: 8.000,00    Líquido: 6.686,98
Quant.de       Base de      Líquido      Líquido que
Tentativas     Cálculo      que Deu      Deveria Dar    Díferença
         1      6.686,98   5.671,95         6.686,98     1.015,03
         2      7.702,01   6.456,63         6.686,98       230,35
         3      7.932,36   6.634,70         6.686,98        52,28
         4      7.984,64   6.675,10         6.686,98        11,88
         5      7.996,52   6.684,30         6.686,98         2,68
         6      7.999,20   6.686,36         6.686,98         0,62
         7      7.999,82   6.686,84         6.686,98         0,14
         8      7.999,96   6.686,95         6.686,98         0,03
         9      7.999,99   6.686,97         6.686,98         0,01
        10      8.000,00   6.686,98         6.686,98          -

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 14 Jun 2008 12:31
por rochinha
Amiguinho,
Spitzer escreveu:Depois desta, considero que minha semana foi muito bem ganha!
Vou mandar o numero de minha conta para receber minha parte, então!!!

Boa sorte

Re: Problema de Lógica - Meus Dois Neurônios Estão em Parafuso!

Enviado: 14 Jun 2008 16:10
por Manuel Luis Modernel
O mestre Rochinha, eu só dei conselhos mais se a coisa tá assim eu tb gostaria de receber um troco hihihihii

gente este forum é excelente pelo nivel de compreensão e camaradagem dele, karacas demorei demias para encontar !!!

Uma Beijunda a todos do veio Modernel !!!