Clipper On Line • Ver Tópico - Funções "RANDOM" não funcionam!

Funções "RANDOM" não funcionam!

Projeto Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

 

Funções "RANDOM" não funcionam!

Mensagempor Ladinilson Sousa » 07 Ago 2020 10:21

Fiz vários testes com nRANDOM(), RANDOM(),  HB_RandomInt(), etc e todas elas NÃO FUNCIONARAM nas suas totalidades ou seja, todas deixaram de fornecer alguns números em uma de range 999999 e estou com muita dificuldade em encontrar uma solução para isso já que em se tratando de sorteios, nenhum número pode faltar ou se repetir.

Algum de vocês tem alguma rotina própria criada para esta função que eu consiga testar?

Obrigado
Ladinilson Sousa
Usuário Nível 1

Usuário Nível 1
 
Mensagens: 33
Data de registro: 09 Fev 2015 10:41
Cidade/Estado: Belém/PA
Curtiu: 1 vez
Mens.Curtidas: 0 vez

Funções "RANDOM" não funcionam!

Mensagempor lucimauro » 07 Ago 2020 11:21

Bom dia,
eu uso assim

result:=hb_random(1,999999)
lucimauro
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 361
Data de registro: 21 Set 2004 21:02
Cidade/Estado: Sobral-CE
Curtiu: 1 vez
Mens.Curtidas: 7 vezes

Funções "RANDOM" não funcionam!

Mensagempor Vlademiro » 07 Ago 2020 11:33

As funções simulam a geração aleatória de números, não tem como impedir a repetição. É como lançar um dado. Não tem como garantir a "não repetição" de números. Vc pode até usar a função para fazer o que vc deseja, mas vai ter que completar via código mesmo.

Pensei aqui em uma solução mas já vi que está incompleta. Mas vou descrever, quem sabe alguém complete ou faça melhor.

(1) O valor sorteado vai ter que ser armazenado em um array. AADD( aArray , valor sorteado )

(2) Sorteia o valor com HB_RandomInt(1,max) // Aqui está o problema, no final eu digo

(3) Verifica se o número sorteado está no array com ASCAN

(4) Se tiver sorteia outro (passo 2)

(5) Se nao tiver exibe

O problema é no passo 2, porque quando os números vão se esgotando a probabilidade de HB_RandomInt retornar um número não sorteado vai diminuir e a função pode demorar demais. Uma alternativa é : caso o número já tenha sido sorteado, vai percorrendo o array até encontrar o superior (ou inferior) não sorteado.

Outra coisa, se for uma função, o array que conterá os números precisa ser STATIC para evitar que ele fique zerado a cada chamada do sorteio

Espero ter ajudado, vamos aguardar alguém melhorar ou trazer outra solução que resolva o seu problema.
Avatar de usuário

Vlademiro
Usuário Nível 4

Usuário Nível 4
 
Mensagens: 674
Data de registro: 11 Jul 2005 02:46
Curtiu: 14 vezes
Mens.Curtidas: 50 vezes

Funções "RANDOM" não funcionam!

Mensagempor Vlademiro » 07 Ago 2020 11:56

Fiz esse aqui mas não testei muito, usa a linha de comando para testar. Acho que está ok, se eu realmente entendi o seu problema corretamente.



PROCEDURE MAIN( n )

    LOCAL x
   
    IF n == NIL
        ? "informe o valor maximo via linha de comando. ex: ex01 10"
        quit
    endif   
    n := VAL( n )
    FOR x := 1 TO n
   
        ? x, Sorteio( n )
       
    NEXT

    RETURN
   
FUNCTION Sorteio( nMax )

    LOCAL nSorteio
    STATIC aSorteio := {}
   
    nSorteio := HB_RandomInt( 1 , nMax )
   
    DO WHILE .T.
        IF Ascan( aSorteio , nSorteio ) == 0 // NAO ACHEI
            AADD( aSorteio , nSorteio ) // ADICIONO PARA NAO REPETIR
            EXIT
        ENDIF
       
        IF ++nSorteio > nMAX
            nSorteio := 1
        ENDIF   
        IF LEN( aSorteio ) == nMax // ACABOU
            EXIT
        ENDIF   
    ENDDO   
   
   

RETURN nSorteio   
Avatar de usuário

Vlademiro
Usuário Nível 4

Usuário Nível 4
 
Mensagens: 674
Data de registro: 11 Jul 2005 02:46
Curtiu: 14 vezes
Mens.Curtidas: 50 vezes

Funções "RANDOM" não funcionam!

Mensagempor Ladinilson Sousa » 07 Ago 2020 12:14

Obrigado meus amigos mas no forum internacional me deram uma solução onde "força" a função a refazer e se testar pois somente ela não resolve.

o teste ficou assim....

function RandomList()

   local aList    := Array( 999999 )
   local nAt, aRandom := {}

   AEval( aList, { |u,i| aList[ i ] := i } )

   do while Len( aList ) > 0
      nAt      := HB_RandomInt( 1, Len( aList ) )
      AAdd( aRandom, aList[ nAt ] )
      ADel( aList, nAt, .t. )
   enddo

   XBROWSER aRandom SHOW RECID

return nil


Valeu
Ladinilson Sousa
Usuário Nível 1

Usuário Nível 1
 
Mensagens: 33
Data de registro: 09 Fev 2015 10:41
Cidade/Estado: Belém/PA
Curtiu: 1 vez
Mens.Curtidas: 0 vez

Funções "RANDOM" não funcionam!

Mensagempor JoséQuintas » 07 Ago 2020 12:47

Vlademiro escreveu:As funções simulam a geração aleatória de números, não tem como impedir a repetição.


Deixou passar isto

Ladinilson Sousa escreveu: todas deixaram de fornecer alguns números... já que em se tratando de sorteios, nenhum número pode faltar ou se repetir.


Talvez algo mais simples:

Funciona de 0 a 9?

Se funciona, sorteia um dígito de cada vez, e junta no final
E no caso do número final repetido, despreza e faz outro.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14697
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 865 vezes

Funções "RANDOM" não funcionam!

Mensagempor Adalberto » 07 Ago 2020 12:53

Amigo, buenas tardes

Hace algunos años tomé una función RAMDOM de Internet, créditos y agradecimientos al autor, mil disculpas por no recordar que creó esa función.

Tal Vez te sea de utilidad.
FUNCTION RandInt(nDesde, nHasta)
LOCAL nUltimo, nRandom:= 0, nMult:= INT(SECONDS())
LOCAL nNumero:= (nHasta - nDesde)
LOCAL nLen:= LEN(ALLTRIM(STR(nNumero)))
//
SET DECIMAL TO 16
IF ((VALTYPE(nUltimo) <> "N") .OR. EMPTY(nUltimo))
   nUltimo:= ((nMult * ((SECONDS() - INT(SECONDS())) * 100)) % 335544319)
ENDIF
nUltimo:= ((nMult * nUltimo) % 335544319)
nRandom:= VAL(RIGHT(STR(nUltimo / 335544319), nLen))
IF (nRandom > nNumero)
   nRandom:= (nNumero - VAL(RIGHT(STR(nRandom), LEN(ALLTRIM(STR(nNumero))) - 1)))
ENDIF
SET DECIMAL TO 2
RETURN(nDesde + INT(nRandom))


Un abrazo, Dios te cuide siempre.

Adalberto
Adalberto
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 322
Data de registro: 01 Set 2007 01:09
Cidade/Estado: Santa Cruz de la Sierra - Bolivia
Curtiu: 0 vez
Mens.Curtidas: 10 vezes

Funções "RANDOM" não funcionam!

Mensagempor Vlademiro » 07 Ago 2020 12:54

Quintas, eu tinha visto, mas creio que essa informação não procede. O que pode ter acontecido é não ter tido tempo suficiente para o número ser sorteado.
Avatar de usuário

Vlademiro
Usuário Nível 4

Usuário Nível 4
 
Mensagens: 674
Data de registro: 11 Jul 2005 02:46
Curtiu: 14 vezes
Mens.Curtidas: 50 vezes

Funções "RANDOM" não funcionam!

Mensagempor JoséQuintas » 07 Ago 2020 13:02

Só não dá pra esperar terminar.
Com 3 dígitos demora pra sair o último número do sorteio de 1.000 números
Acima de 3 dígitos, vai longe.
Mas não vai sortear tanto número assim.

#include "inkey.ch"
#define NUM_LIMITE 999999
#define NUM_DIGITOS 6

PROCEDURE Main

   LOCAL aList := {}, nCont, nKey

   SetMode( 30, 100 )
   CLS
   FOR nCont = 1 TO NUM_LIMITE
      IF nKey == K_ESC .OR. Len( aList ) = NUM_LIMITE
         EXIT
      ENDIF
      Sorteia( aList, @nKey )
   NEXT

   Inkey(0)

   RETURN

STATIC FUNCTION Sorteia( aList, nKey )

   LOCAL nCont, cNumero

   DO WHILE .T.
      nKey := Inkey()
      IF nKey == K_ESC
         EXIT
      ENDIF
      cNumero := ""
      FOR nCont = 1 TO NUM_DIGITOS
         cNumero += Str( hb_Random( 0, 9 ), 1 )
      NEXT
      IF hb_ASCan( aList, Val( cNumero ) ) == 0
         AAdd( aList, Val( cNumero ) )
         ? Time(), Len( aList ), Val( cNumero )
         EXIT
      ENDIF
   ENDDO

   RETURN NIL
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14697
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 865 vezes

Funções "RANDOM" não funcionam!

Mensagempor JoséQuintas » 07 Ago 2020 13:07

Outra opção seria criar um array com todos os números e ir sorteando só os que tem:

Vou tentar enquanto digito no fórum, pode conter erros, algo do tipo

LOCAL aList := {}, nKey := 0

FOR nCont = 1 TO 999999
   AAdd( aList, nCont )
NEXT
DO WHILE .T.
   nKey := Inkey()
   IF Len( aList ) == 0 .OR. nKey == K_ESC
      EXIT
   ENDIF
   nPos := hb_Random( 1, Len( nCont ) )
   ? aList[ nPos )
   hb_Adel( aList, nPos, .T. )
ENDDO

RETURN
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14697
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 865 vezes

Funções "RANDOM" não funcionam!

Mensagempor JoséQuintas » 07 Ago 2020 13:19

Testado/Testando:


#include "inkey.ch"

PROCEDURE Main

   LOCAL aList := {}, nKey := 0, cTime, nCont, nPos

   SetMode( 25, 80 )
   CLS
   cTime     := Time()
   FOR nCont = 1 TO 999999
      AAdd( aList, nCont )
   NEXT
   DO WHILE nKey != K_ESC
      nKey := Inkey()
      IF Len( aList ) == 0
         EXIT
      ENDIF
      nPos := hb_Random( 1, Len( aList ) )
      IF Mod( Len( aList ), 1000 ) == 0
         ? Time(), Len( aList ), aList[ nPos ]
      ENDIF
      hb_Adel( aList, nPos, .T. )
   ENDDO
   ? cTime, Time()
   Inkey(0)

   RETURN


sorteio.png


média de 1.000 números a cada 4 segundos
Não vou esperar terminar
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14697
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 865 vezes

Funções "RANDOM" não funcionam!

Mensagempor JoséQuintas » 07 Ago 2020 13:33

Esse último pode não ser bom.
Depende de uma coisa:

Notou que certos números não saem.
São sempre os mesmos?

Se forem sempre os mesmos, então pode deixar todo sorteio viciado.
Se cada vez que roda, são números diferentes, aí sim, sem problema.

Criando o array, o sorteio vai ser somente do intervalo de elementos do array, e de números que não foram sorteados ainda.
Com certeza o resultado final é sortear todos os números existentes.

No primeiro sorteio o random retorna 1 a 999999
no segundo, 1 a 999998
e assim por diante

o número sorteado não vai ser o randômico, mas o elemento do array que corresponde à posição sorteada.

Pode até criar outra rotina que gera os números de forma randômica no array, antes de começar a sortear, pra deixar mais embaralhado ainda.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14697
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 865 vezes

Funções "RANDOM" não funcionam!

Mensagempor Claudio Soto » 07 Ago 2020 14:18

JoséQuintas escreveu:Notou que certos números não saem.
São sempre os mesmos?

Probaste reiniciar cada tanto la "semilla" del generador de números pseudoaleatorios llamando:
HB_RandomSeed()

En un loop tan grande como la generación de los números es con una función matemática cuyo resultado depende del numero anterior puede que entre en un espiral de repetición
Saludos.
Dr. Claudio Soto
(Uruguay)
http://srvet.blogspot.com
Avatar de usuário

Claudio Soto
Colaborador

Colaborador
 
Mensagens: 552
Data de registro: 27 Ago 2012 12:31
Cidade/Estado: Uruguay
Curtiu: 34 vezes
Mens.Curtidas: 153 vezes

Funções "RANDOM" não funcionam!

Mensagempor Ladinilson Sousa » 07 Ago 2020 16:01

Obrigado pelo debate.

No caso seria para criação de cartelas tipo rifas que vão de 1 a 999999 ou seja, seis dígitos e as funções testadas não se obtém TODOS os números aleatórios de 1 a 999999 sempre deixavam alguns faltando.
Pois bem, fiz um DBF de 1 a 999999 e usava a função hb_randomint() para mudar o ponteiro aleatoriamente e "catar" esses números e mesmo assim falhavam.

A função apresentada pelo fórum Internacional supriu este problema usando ARRAY que tem a mesma idéia do que fiz com DBF mas de maneira a "forçar" a função a não "falhar".

No fórum Internacional tem uma observação sobre as funções RANDOM e parecem que funcionam apenas para 4 dígitos no máximo ou seja, até 9999.

Abraços
Ladinilson Sousa
Usuário Nível 1

Usuário Nível 1
 
Mensagens: 33
Data de registro: 09 Fev 2015 10:41
Cidade/Estado: Belém/PA
Curtiu: 1 vez
Mens.Curtidas: 0 vez

Funções "RANDOM" não funcionam!

Mensagempor Claudio Soto » 07 Ago 2020 16:28

Todas las funciones que generan números aleatorios generan un numero decimal entre 0 y 1. Luego para generar un numero aleatorio entero se hace asi:
Nro entero = INT (NroMax * AleatorioDecimal0y1 + NroMin)

En consecuencia los números generados van a depender de la precisión decimal del numero aleatorio generado entre 0 y 1

Por ejemplo si la precisión fuera de 1 dígito decimal sólo se podrán generar:
0, 0.1, 0.2, ... ,0.9, 1.0

Si con la formula anterior queremos generar un numero entre 1 y 100,
Solo generaran 1,10,20, ... 90, 100
jamás podremos tener 23, 34, 67, etc.
Saludos.
Dr. Claudio Soto
(Uruguay)
http://srvet.blogspot.com
Avatar de usuário

Claudio Soto
Colaborador

Colaborador
 
Mensagens: 552
Data de registro: 27 Ago 2012 12:31
Cidade/Estado: Uruguay
Curtiu: 34 vezes
Mens.Curtidas: 153 vezes

Próximo



Retornar para Harbour

Quem está online

Usuários vendo este fórum: Ahrefs [Bot], Google [Bot], Semrush [Bot] e 6 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro