Página 1 de 2
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 10:21
por Ladinilson Sousa
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 11:21
por lucimauro
Bom dia,
eu uso assim
result:=hb_random(1,999999)
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 11:33
por Vlademiro
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.
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 11:56
por Vlademiro
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 12:14
por Ladinilson Sousa
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 12:47
por JoséQuintas
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.
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 12:53
por Adalberto
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 12:54
por Vlademiro
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.
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 13:02
por JoséQuintas
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 13:07
por JoséQuintas
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 13:19
por JoséQuintas
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
média de 1.000 números a cada 4 segundos
Não vou esperar terminar
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 13:33
por JoséQuintas
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.
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 14:18
por Claudio Soto
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 16:01
por Ladinilson Sousa
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
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 16:28
por Claudio Soto
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.
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 17:04
por JoséQuintas
Então parece que aquela rotina de gerar um número de cada vez pode ser a mais adequada.
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 18:22
por Claudio Soto
Si es lo mas seguro, porque a pesar que en C:
float : 7 dígitos de precisión decimal
double : 15 dígitos
Hay diferentes funciones para generar números pseudoaleatorios y hay que ver si la función realmente recorre todo el espectro de presicion decimal o entra en un loop más o menos infinito y luego de una determinado número de cálculo vuelve a empezar del inicio de la serie.
Se llaman pseudoaleatorios porque no son verdaderamente aleatorios, siempre la funcion parte de un valor inicial y si siempre se da el mismo valor inicial ("semilla") siempre arroja la misma secuencia de números.
Generalmente como semilla se usa la hora y la fecha actual del sistema en segundos o milisegundos para asegurarse que la secuencia de números sea diferente en cada corrida.
Funções "RANDOM" não funcionam!
Enviado:
07 Ago 2020 18:47
por alxsts
Olá!
Provavelmente trocando o uso de arrays pelo de hashes torne o processo mais rápido
Funções "RANDOM" não funcionam!
Enviado:
03 Set 2020 11:07
por Linguagemclipper
Eu uso a seguinte função para gerar números aleatórios para nomes de arquivos temporários:
function Ran( nLimite )
static nGuarda:= 1
local I
local nResult
if ValType( nLimite ) # [N]
nLimite:= 100
endif
I:= Seconds()
while nLimite > I
I:= I * 100 +Seconds()
enddo
nGuarda:= (nGuarda +I) / (nResult:= nGuarda * I % nLimite +1)
nResult:= Int( nResult )
return nResult
Essa função retorna um número de 0 até o número passado como parâmetro para ela.
Exemplo:
cRANDOM := ALLTRIM(STR(RAN(9999)))
fINDEX := xTEMP+"TEMP" + cRANDOM
Funções "RANDOM" não funcionam!
Enviado:
20 Set 2020 20:03
por Eduardo Pinho
Talvez o debate já tenha se encerrado, mas se der tempo, tenho uma funcao aqui que pra mim funciona bem.
Baixei na net nao sei onde, e só fiz adaptacao pra parametros de intervalo.
Fiz muitos testes nela, e nunca vi falha, distribuicao irregular, essas coisas...
func RND && ( Min, Max )
* Esta funcao gera um numero aleatorio entre min e max (inclusive).
*
* Returns a floating-point pseudo-random number (PRN) between 0 and maxval
* (left-inclusive), with maxval defaulting to 1. If maxval is in the same
* order of size as the generator's period, the distribution of the
* resulting PRNs will be irregular, but since PERIOD is 2147483647, that
* should not be a problem in practice; people doing astrophysics or monte
* carlo simulation using Clipper deserve everything they get, anyway .
*
* Adaptada para o Harbour com 2 parametros: limite min e maximo,
* mantendo maxval sempre 1.
* Sem os parametros min e max retorna o random como foi gerado.
*
* Esta funcao nao funciona se RND_SEED nao puder ir se modificando a cada chamada.
* Portanto, um executavel gerando um unico PRN e sendo chamado varias vezes em um
* arquivo BAT, por exemplo, irá gerar uma distruibuicao irregular que em nada se
* parecerá com numeros aleatorios.
*
* Para gerar numeros aleatorios seguidamente, use esta funcao seguidamente no mesmo
* executavel.
*
para min,max
private nRandom,nmaxval,range
IF TYPE([RND_PERIOD])#[N]
PUBLIC RND_PERIOD,RND_FACTOR,RND_SEED
RND_PERIOD=2147483647
RND_FACTOR=16807
rnd_seed = 0
ENDIF
do while rnd_Seed = 0
rnd_Seed = Seconds()
rnd_Seed = ( rnd_Seed * 12345 ) % RND_PERIOD
enddo
rnd_Seed = RND_FACTOR * rnd_Seed - Int(RND_FACTOR * rnd_Seed / RND_PERIOD ) * RND_PERIOD
nRandom = (rnd_Seed / RND_PERIOD)
if pcount()=2
range=max-min+1
nrandom = int(nrandom*range+min)
endif
RETURN nRandom
Funções "RANDOM" não funcionam!
Enviado:
20 Set 2020 21:21
por Vlademiro
Até o momento, a única forma que eu encontrei para garantir a não repetição de valores foi através de uma variável Static.
Static nVal := 0
nValorFinal := hb_randomint(1000,9999) + nVal++
Return nValorFinal
Funções "RANDOM" não funcionam!
Enviado:
20 Set 2020 21:24
por Vlademiro
Eduardo, essa sua da certo tb, é o mesmo princípio.
Valeu.