Página 1 de 2

double int no Harbour?

Enviado: 15 Jul 2019 13:43
por ArnaldoND
como inicializar uma variavel double int no harbour?

preciso de uma variavel numerica muito grande, pois fiz uma função que faz a consistencia do digito de verificação do numero do processo do TJSP, cujo calculo se baseia em:

1111111-DD-2222-3-44-555555

onde:
DD = 98 - MOD ( 11111112222344555555 , 97 )
ou
DD = 98 - ( 11111112222344555555 % 97 )

Quando 1111111 está "cheio", a função está calculando errado! acredito q se deva ao tamanho do numero , que é inteiro.. porque? se eu calculo o seguinte numero de processo: 0004939-48-2013-8-26-029900, o resultado é OK (retorna-me 48), porém, se eu tento 1044645-26-2019-8-26-010000, retorna um numero nada a ver, provavelmente devido à truncamento durante a manipulação da variavel

double int no Harbour?

Enviado: 15 Jul 2019 14:33
por JoséQuintas
Talvez dividir no meio e fazer em duas etapas.
A precisão numérica é de 16 caracteres, e aí tem mais que isso.
Supondo que sejam 22 dígitos, dois blocos de 11.
Como na primeira operação vai sobrar no máximo 96, concatenado ao segundo vão ser apenas 13.

double int no Harbour?

Enviado: 15 Jul 2019 14:38
por JoséQuintas
Direto no fórum, não testei....

Código: Selecionar todos

cNumeroGrande := Padl( cOriginal, 24 )

cParte1 := Substr( cNumeroGrande, 1, 12 )
nResto := Mod( Val( cParte1 ), 97 )

cParte2 := StrZero( nResto, 2 ) + Substr( cNumeroGrande, 13 )
nResto := Mod( Val( cParte2 ), 97 )

double int no Harbour?

Enviado: 15 Jul 2019 14:49
por asimoes
Tenho esse fonte veja se te ajuda:

Incluir no hpb

Funções:

C_SUM -> Soma
C_SUB ->Subtração
C_MULT -) Multiplicação
C_DIV - Divisão

double int no Harbour?

Enviado: 15 Jul 2019 15:11
por ArnaldoND
JoseQuintas, tua solução foi perfeita... a matemática é fascinante kkk
obrigado

double int no Harbour?

Enviado: 15 Jul 2019 15:39
por JoséQuintas
É parecido com o que a gente faz "a caneta", exceto que não olhamos pelos zeros

85 / 3

8 / 3 = 2 sobra 2
junta o 2 no 5 que tinha sobrado temos 25
25 / 3 = 8 sobra 1

Nessa divisão em duas partes... é como se fosse 80 / 30, que sobra 20, trabalhando tudo na mesma grandeza, dezena.
"2" + "5", por causa da posição do número, o 2 acaba representando os 20, sem precisar fazer outra conta.
Digamos que é usar truques, pra facilitar contas.

Basicamente o mesmo jeito de fazer "a caneta", mas ajustado para quantidade de casas que o Harbour "aguenta", pra não precisar muita conta.

double int no Harbour?

Enviado: 15 Jul 2019 17:14
por asimoes
Não sei qual é o resultado esperado na sua rotina

? C_RESTO( NN, DD)

Código: Selecionar todos

#pragma BEGINDUMP

#include <windows.h>
#include <windef.h>
#include <tlhelp32.h>
#include <hbapi.h>
#include <hbapiitm.h>

HB_FUNC ( C_RESTO )
{
        
  ULONGLONG para1;
  ULONGLONG para2;
  ULONGLONG resulta;
        
  para1 = hb_parnint(1);
  para2 = hb_parnint(2);

  resulta = (para1 % para2);

  hb_retnll(resulta);

}
#pragma ENDDUMP

double int no Harbour?

Enviado: 15 Jul 2019 17:41
por JoséQuintas
asimoes escreveu:Não sei qual é o resultado esperado na sua rotina
Inverto a pergunta:
Como vai passar os números com mais de 16 dígitos, se o limite do Harbour é 16 dígitos?

? c_Resto( 55555555555555555555, 33333333333333333333)

double int no Harbour?

Enviado: 15 Jul 2019 17:53
por JoséQuintas
Xi..... Fiz uns testes...

Código: Selecionar todos

PROCEDURE Main

   LOCAL a, b

   a := 555555555555555555555
   b := 333333333333333333333
   ? c_Resto( a, b )
   Inkey(0)

   RETURN
Retornou zero
Acho que acabou com limite baixo.

double int no Harbour?

Enviado: 15 Jul 2019 17:59
por JoséQuintas
O difícil agora é conferir kkkk

Código: Selecionar todos


PROCEDURE Main

   LOCAL a, b

   a := 555555555555555555555
   b := 97
   ? c_Resto( a, b )
   ? Resto( "555555555555555555555", 97 )
   Inkey(0)

   RETURN

#pragma BEGINDUMP

#include <windows.h>
#include <windef.h>
#include <tlhelp32.h>
#include <hbapi.h>
#include <hbapiitm.h>

HB_FUNC ( C_RESTO )
{

  ULONGLONG para1;
  ULONGLONG para2;
  ULONGLONG resulta;

  para1 = hb_parnint(1);
  para2 = hb_parnint(2);

  resulta = (para1 % para2);

  hb_retnll(resulta);

}
#pragma ENDDUMP

FUNCTION Resto( cOriginal, nDivide )

   LOCAL cNumeroGrande, cParte1, cParte2, nResto

cNumeroGrande := Padl( cOriginal, 24 )

cParte1 := Substr( cNumeroGrande, 1, 12 )
nResto := Mod( Val( cParte1 ), nDivide )

cParte2 := StrZero( nResto, 2 ) + Substr( cNumeroGrande, 13 )
nResto := Mod( Val( cParte2 ), nDivide )

RETURN nResto
Um retorna 79 e outro 17

double int no Harbour?

Enviado: 15 Jul 2019 18:07
por JoséQuintas
Solução pro teste mais fácil:

Código: Selecionar todos


PROCEDURE Main

   LOCAL a, b

   a := 333333333333333333333
   b := 3
   ? c_Resto( a, b )
   ? Resto( "333333333333333333333", b )
   Inkey(0)

   RETURN
Em C sobra 2, o que é errado, porque o número é divisível por 3....
Realmente o limite não é suficiente para o cálculo que precisa.

double int no Harbour?

Enviado: 15 Jul 2019 18:13
por JoséQuintas
Correção:
os parâmetros numéricos acabam recebendo o número de precisão limitada do Harbour.
Precisa de cuidado sobre aonde ela pode ajudar.

double int no Harbour?

Enviado: 15 Jul 2019 20:52
por asimoes
Quintas,

Pode testar por aqui:
https://www.4devs.com.br/resto_da_divisao

double int no Harbour?

Enviado: 15 Jul 2019 21:29
por asimoes
Em C pode-se usar fmod ou %

Código: Selecionar todos

#pragma BEGINDUMP

#include <windows.h>
#include <windef.h>
#include <tlhelp32.h>
#include <hbapi.h>
#include <hbapiitm.h>

HB_FUNC ( C_RESTO )
{
        
  ULONGLONG para1;
  ULONGLONG para2;
  double resulta;
        
  para1 = hb_parnint(1);
  para2 = hb_parnint(2);

  //resulta = (para1 % para2); // ou usando fmod 
  
  resulta = fmod( para1, para2 );
  
  hb_retnd(resulta); // retorna double
  
  //hb_retni(resulta); //retorna integer

}
#pragma ENDDUMP

double int no Harbour?

Enviado: 15 Jul 2019 21:33
por asimoes
Função Mod do harbour

Código: Selecionar todos

/*
 * Mod() function
 *
 * Copyright 1999 Matthew Hamilton <mhamilton@bunge.com.au>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file LICENSE.txt.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
 *
 * As a special exception, the Harbour Project gives permission for
 * additional uses of the text contained in its release of Harbour.
 *
 * The exception is that, if you link the Harbour libraries with other
 * files to produce an executable, this does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * Your use of that executable is in no way restricted on account of
 * linking the Harbour library code into it.
 *
 * This exception does not however invalidate any other reasons why
 * the executable file might be covered by the GNU General Public License.
 *
 * This exception applies only to the code released by the Harbour
 * Project under the name Harbour.  If you copy code from other
 * Harbour Project or Free Software Foundation releases into a copy of
 * Harbour, as the General Public License permits, the exception does
 * not apply to the code that you add in this way.  To avoid misleading
 * anyone as to the status of such modified files, you must delete
 * this exception notice from them.
 *
 * If you write modifications of your own for Harbour, it is your choice
 * whether to permit this exception to apply to your modifications.
 * If you do not wish that, delete this exception notice.
 *
 */

#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapierr.h"
#include "hbmath.h"

/* NOTE: In CA-Cl*pper this is written in Clipper, see the source below,
         and the error handling is NOT made here, but in the % operator.
         [vszakats] */

/* NOTE: CA-Cl*pper is buggy since it relies on the fact that the errorhandler
         will silently handle zero division errors. [vszakats] */

/* NOTE: This C version fully emulates the behaviour of the original
         CA-Cl*pper version, including bugs/side-effects. [vszakats] */

HB_FUNC( MOD )
{
   PHB_ITEM pNumber = hb_param( 1, HB_IT_NUMERIC );
   PHB_ITEM pBase   = hb_param( 2, HB_IT_NUMERIC );

   if( pNumber && pBase )
   {
      double dNumber = hb_itemGetND( pNumber );
      double dBase   = hb_itemGetND( pBase ); /* dBase! Cool! */

      if( dBase )
      {
         double dResult = fmod( dNumber, dBase );

         if( dResult && ( dNumber > 0 ? dBase < 0 : dBase > 0 ) )
            dResult += dBase;
         hb_retnd( dResult );
      }
      else
      {
         PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ZERODIV, 1341, NULL, "%", HB_ERR_ARGS_BASEPARAMS );

         /* In CA-Cl*pper Mod() function ignores substitution result
          * and return original numeric item keeping its internal
          * representation: integer or double, size and number of
          * decimal places, it can be seen in code like:
          *    PROCEDURE Main()
          *       Set( _SET_FIXED, .T. )
          *       ? Transform( Mod( 12345, 0 ), "" )
          *       RETURN
          *
          * [druzus]
          */
         if( pResult )
         {
            hb_itemReturn( pNumber );
            hb_itemRelease( pResult );
         }
      }
   }
   else
      hb_errRT_BASE_SubstR( EG_ARG, 1085, NULL, "%", 2, hb_param( 1, HB_IT_ANY ), hb_param( 2, HB_IT_ANY ) );
}

/*
   FUNCTION Mod( cl_num, cl_base )

      LOCAL cl_result := cl_num % cl_base

      RETURN iif( cl_base = 0, cl_num, iif( cl_result * cl_base < 0, cl_result + cl_base, cl_result ) )
 */