Funções "RANDOM" não funcionam!
Moderador: Moderadores
-
Ladinilson Sousa
- Usuário Nível 1

- Mensagens: 35
- Registrado em: 09 Fev 2015 11:41
- Localização: Belém/PA
Funções "RANDOM" não funcionam!
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
Algum de vocês tem alguma rotina própria criada para esta função que eu consiga testar?
Obrigado
Funções "RANDOM" não funcionam!
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.
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.
Funções "RANDOM" não funcionam!
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.
Código: Selecionar todos
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
-
Ladinilson Sousa
- Usuário Nível 1

- Mensagens: 35
- Registrado em: 09 Fev 2015 11:41
- Localização: Belém/PA
Funções "RANDOM" não funcionam!
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....
Valeu
o teste ficou assim....
Código: Selecionar todos
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
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Funções "RANDOM" não funcionam!
Deixou passar istoVlademiro escreveu:As funções simulam a geração aleatória de números, não tem como impedir a repetição.
Talvez algo mais simples: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.
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.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/
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/
-
Adalberto
- Usuário Nível 3

- Mensagens: 343
- Registrado em: 01 Set 2007 01:09
- Localização: Santa Cruz de la Sierra - Bolivia
Funções "RANDOM" não funcionam!
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.
Un abrazo, Dios te cuide siempre.
Adalberto
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.
Código: Selecionar todos
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))
Adalberto
Funções "RANDOM" não funcionam!
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.
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Funções "RANDOM" não funcionam!
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.
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.
Código: Selecionar todos
#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.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/
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/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Funções "RANDOM" não funcionam!
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
Vou tentar enquanto digito no fórum, pode conter erros, algo do tipo
Código: Selecionar todos
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.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/
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/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Funções "RANDOM" não funcionam!
Testado/Testando:
média de 1.000 números a cada 4 segundos
Não vou esperar terminar
Código: Selecionar todos
#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
Não vou esperar terminar
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/
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/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Funções "RANDOM" não funcionam!
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.
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.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/
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/
-
Claudio Soto
- Colaborador

- Mensagens: 566
- Registrado em: 27 Ago 2012 12:31
- Localização: Uruguay
- Contato:
Funções "RANDOM" não funcionam!
Probaste reiniciar cada tanto la "semilla" del generador de números pseudoaleatorios llamando:JoséQuintas escreveu: Notou que certos números não saem.
São sempre os mesmos?
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
-
Ladinilson Sousa
- Usuário Nível 1

- Mensagens: 35
- Registrado em: 09 Fev 2015 11:41
- Localização: Belém/PA
Funções "RANDOM" não funcionam!
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
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
-
Claudio Soto
- Colaborador

- Mensagens: 566
- Registrado em: 27 Ago 2012 12:31
- Localização: Uruguay
- Contato:
Funções "RANDOM" não funcionam!
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.
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.
