Função extenso passo a passo

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Só quando fui converter pra MySQL é que "enxerguei" como ficou fácil.
Sempre pensei de fora pra dentro, mas de dentro pra fora fica muuuito mais fácil.

Acompanhem....

Regra básica de programação:
Dividir o problemão em probleminhas....

O menor problema é..... um único número.
Sem usar array, ou economia de fonte...

Código: Selecionar todos

FUNCTION ExtensoUnidade( nValor )

LOCAL cTxt := ""

DO CASE
CASE nValor == 1; cTxt := "HUM"
CASE nValor == 2; cTxt := "DOIS"
CASE nValor == 3; cTxt := "TRES"
CASE nValor == 4; cTxt := "QUATRO"
CASE nValor == 5; cTxt := "CINCO"
CASE nValor == 6; cTxt := "SEIS"
CASE nValor == 7; cTxt := "SETE"
CASE nValor == 8; cTxt := "OITO"
CASE nValor == 9; cTxt := "NOVE"
CASE nValor == 10; cTxt := "DEZ"
CASE nValor == 11; cTxt := "ONZE"
CASE nValor == 12; cTxt := "DOZE"
CASE nValor == 13; cTxt := "TREZE"
CASE nValor == 14; cTxt := "QUATORZE"
CASE nValor == 15; cTxt := "QUINZE"
CASE nValor == 16; cTxt := "DEZESSEIS"
CASE nValor == 17; cTxt := "DEZESSETE"
CASE nValor == 18; cTxt := "DEZOITO"
CASE nValor == 19; cTxt := "DEZENOVE"
ENDCASE

RETURN cTxt
Olhem com atenção:
NADA complicado, tudo simples, resolvido de 1 a 19.
Qualquer programador consegue fazer isso, em qualquer linguagem de programação, porque só tem comando básico.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Agora vamos para 2 dígitos.
Até 19 resolvido.
Agora vém 20 a 99
Precisaremos separar o primeiro e o segundo dígito pra isso.
Podemos usar substr(Str()) ou função de divisão com Int() e/ou resto de divisão.
Fazer usando tudo básico, sem economizar fonte.

Código: Selecionar todos

FUNCTION ExtensoDezena( nValor )

   LOCAL cTxt := ""

   IF nValor == 0
      RETURN cTxt
   ENDIF
   IF nValor < 20
      RETURN ExtensoUnidade( nValor )
   ENDIF
Até 19 resolvido, agora acima disso vamos dividir os dois dígitos

Código: Selecionar todos

   nDezena := Int( nValor / 10 )
   nUnidade := nValor - ( nDezena * 10 )
   DO CASE
   CASE nDezena == 2; cTxt := "VINTE"
   CASE nDezena == 3; cTxt := "TRINTA"
   CASE nDezena == 4; cTxt := "QUARENTA"
   CASE nDezena == 5; cTxt := "CINQUENTA"
   CASE nDezena == 6; cTxt := "SESSENTA"
   CASE nDezena == 7; cTxt := "SETENTA"
   CASE nDezena == 8; cTxt :=  "OITENTA"
   CASE nDezena == 9; cTxt :=  "NOVENTA"
   ENDCASE
Pronto, resolvido o primeiro dígito.
Agora o segundo dígito.

Código: Selecionar todos

IF nUnidade != 0
   cTxt += " E " + ExtensoUnidade( nUnidade )
ENDIF

RETURN cTxt
Pronto.
Tudo simples.
Agora temos de 1 a 99.

Eu nunca tinha visto por este lado, de fazer de dentro pra fora, muito mais fácil deste jeito.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Agora de 1 a 999.
Bem parecido com o anterior, só que vamos dividir por 100 ao invés de por 10.

Código: Selecionar todos

FUNCTION ExtensoCentena( nValor )

   LOCAL cTxt := "", nCentena, nDezena

   IF nValor == 0
      RETURN cTxt
   ENDIF
   IF nValor < 100
      RETURN ExtensoDezena( nValor )
   ENDIF
Até 99 já temos.

Código: Selecionar todos

IF nValor == 100
   RETURN "CEM"
ENDIF
CEM é exceção, resolvido, agora separar os dígitos.

Código: Selecionar todos

nCentena := Int( nValor / 100 )
nDezena := nValor - ( nCentena * 100 )
Mesma coisa do anterior, temos o primeiro dígito e o resto

Código: Selecionar todos

DO CASE
CASE nCentena == 1; cTxt := "CENTO"
CASE nCentena == 2; cTxt := "DUZENTOS"
CASE nCentena == 3; cTxt := "TREZENTOS"
CASE nCentena == 4; cTxt := "QUATROCENTOS"
CASE nCentena == 5; cTxt := "QUINHENTOS"
CASE nCentena == 6; cTxt := "SEISCENTOS"
CASE nCentena == 7; cTxt := "SETECENTOS"
CASE nCentena == 8; cTxt := "OITOCENTOS"
CASE nCentena == 9; cTxt := "NOVECENTOS"
ENDCASE
Pronto, resolvida a primeira parte, agora a segunda, parecida com a rotina de dezena.

Código: Selecionar todos

IF nDezena != 0
   cTxt += " E  " + ExtensoDezena( nDezena )
ENDIF

RETURN cTxt
Pronto.
Tudo simples.
Agora temos de 1 a 999.

Repetindo: de dentro pra fora, do menor para o maior, tá muito fácil.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Como exemplo, com o que temos até aqui, poderíamos mostrar de 0.01 centavo a 999.99
Mesmo esquema, dividindo a parte inteira e a decimal.

Código: Selecionar todos

FUNCTION Extenso( nValor )

   LOCAL cTxt := ""

   nInteiro := Int( nValor )
   nDecimal := ( nValor - Int( nValor ) ) * 100

   IF nInteiro != 0
      cTxt += ExtensoCentena( nValor ) + " " + iif( nInteiro == 1, "REAL", "REAIS" )
   ENDIF
Resolvido reais, agora centavos, temos o ajuste do texto em portugues também pra fazer.

Código: Selecionar todos

   IF nDecimal != 0
      IF nInteiro != 0
         cTxt += " E "
      ENDIF
     cTxt += ExtensoCentena( nDecimal ) + " " + iif( nDecimal == 1, "CENTAVO", "CENTAVOS" )
   ENDIF

   RETURN cTxt
É só pra exemplo. Com as rotinas acima temos o extenso de 0.01 a 999.99.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

O que muda num valor acima de 999?
999 999 999
Que vamos separar de 3 em 3, fazer o extenso igual foi feito até agora, mas cada um tem um nome: bilhão, milhão, mil

Então vamos precisar um contador, pra saber qual o grupo que estamos fazendo, e qual o nome que vamos utilizar.
Se for 1 é singular, se for mais de um é plural.
Mas é a rotina que já fizemos pra traduzir o número, acrescentado do texto de unidade.

Código: Selecionar todos

FUNCTION ExtensoNumero( nValor )

   LOCAL cTxt, cValorTexto, nGrupo

   cValorTexto  := StrZero( nValor, 15 )

   FOR nCont = 1 TO 5
      nValorAtual := Val( Substr( cValorTexto, ( nCont * 3 - 2 ), 3 ) )
      nResto        := Val( Substr( cValorTexto, ( nCont * 3 ) )
      IF nValorAtual != 0
         cTxt += ExtensoCentena( nValorAtual )
         DO CASE
        CASE nGrupo == 1; cTxt += iif( nValorAtual == 1, "QUATRILHAO, "QUATRILHOES" )
        CASE nGrupo == 2; cTxt += iif( nValorAtual ==1, "TRILHAO", "TRILHOES" )
         CASE nGrupo == 3; cTxt += iif( nValorAtual == 1, "BILHAO", "BILHOES" )
        CASE nGrupo == 4; cTxt += "MIL"
        ENDCASE
      ENDIF
      IF nResto != 0
         cTxt += " E "
      ENDIF
   NEXT
   
   RETURN cTxt
Pronto.
Juntando tudo, e alterando a rotina Extenso() pra usar ExtensoNumero() ao invés de ExtensoCentena() temos a rotina de extenso.
Nesta aqui apenas dividimos o número de 3 em 3, e aplicamos a rotina anterior de centena.

Como ajuste final, podemos alterar pra quando for ILHAO REAIS, pra mostrar ILHAO DE REAIS.

Código: Selecionar todos

IF "ILHAO REAIS" $ cTxt
   cTxt := StrTran( cTxt, "ILHAO REAIS", "ILHAO DE REAIS" )
ENDIF
Esta aqui já varia entre linguagens de programação, porque no MySQL por exemplo não tem FOR/NEXT, ou STRZERO().
Pra substituir o StrZero() podemos usar o LPAD( numero, 15, '0' )
E pra substituir o FOR/NEXT, pode ser o DO WHILE.
Mas basicamente seria a mesma coisa.

Então, de dentro pra fora, do menor para o maior, a rotina acaba ficando super simples.
Só percebi isso algum tempo depois de converter para o MySQL.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

E é lógico, em Harbour podemos usar array.
Pra fazer as unidades, dezenas e centenas, e até o valor monetário, poderia reduzir o DO CASE a um array.

Código: Selecionar todos

aList := { "UM", "DOIS", "TRES", "QUATRO", "CINCO", ... }
cTxt := aList[ nValor ]
Mas é interessante a básica, porque pode ser aplicada em outras linguagens de programação que não tenham array.

Inclusive no Harbour, usei recursividade nisso de grupos, separando três numeros a cada rodada, até acabar o número.
Mas no MySQL não tem recursividade... então tive que mudar isso.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Pensando bem...

Está aí um bom exemplo de código fonte simples.

Usar recursividade foi interessante.... mas já não tinha isso no MySQL
Usar array no Harbour simplifica muito... mas não tinha isso no MySQL
O bom e velho DO CASE atendeu bem a Harbour e MySQL.

Não que não seja pra usar recursos que existam na linguagem de programação....

Mas é como eu disse aqui algumas vezes:
Se ficar craque no básico, pode resolver muita coisa, e pode usar até melhor recursos avançados, quando existirem.

E volto a comentar sobre o uso de -w3 -es2.
É como se a gente voltasse no tempo, e reaprendesse a programar o básico.
E ficar craque no básico, na parte que deixamos escapar antes.
A partir daí, nosso básico pode resolver qualquer parada, inclusive pra entender o mais avançado.

E o que tem a ver com esse extenso?

Usando -w3 -es2, declarando variáveis, vi que separando em rotinas menores, "por assunto", acaba precisando menos variáveis, ou até permitindo o uso de variáveis com mesmo nome.
Isso simplifica muito o trabalho.

Esta rotina de extenso divide em rotinas onde cada uma trata "de seu assunto", por isso ficou simples.
Rotinas simples, pra problemas simples, que resolveram um problemão que era complicado.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Função extenso passo a passo

Mensagem por alxsts »

Olá!

Não é uma questão técnica, só
comentário relativo ao assunto: Hum ou um?
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Encontrei este, que alteraria esse extenso, principalmente a parte dos centavos.

https://www.normaculta.com.br/como-escr ... r-extenso/
extenso.png
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

extenso2.png
E aqui mostra sem o "E" entre os grupos, exceto se o grupo for apenas com centena.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

extenso3.png
Só pra rir um pouquinho.....
O oito é redondo, porque é feito com círculos.
Não sei se foi um bom exemplo pra números redondos kkkkk
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Mas agora o que interessa:

A informação dessa página que encontrei é confiável?
Alguém tem informação sobre esses detalhes?
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Esta parte me deixou na dúvida
Professora de português, revisora e lexicógrafa nascida no Rio de Janeiro e licenciada pela Escola Superior de Educação do Porto, em Portugal (2005). Atua nas áreas da Didática e da Pedagogia.
será português de Portugal, ou português do Brasil, apesar de serem REAIS.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Achei esta:

http://www.linguabrasil.com.br/img/colu ... -06-10.pdf
extenso4.png
Isso dividiria a rotina de extenso em duas, a não ser que os bancos alteraram a exigência para preenchimento por computador.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Função extenso passo a passo

Mensagem por JoséQuintas »

Uma das partes, moleza.

Código: Selecionar todos

   IF nDecimal != 0
      IF nInteiro != 0
         cTxt += " E "
      ENDIF
      cTxt += ze_ExtensoNumero( nDecimal )
      cTxt += " " + iif( nDecimal == 1, "CENTAVO", "CENTAVOS" ) 
      cTxt += iif( nInteiro == 0, " DE REAL", "" )
   ENDIF
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder