il problema non sta nella funzione di generazione dei numeri casuali di vb, ma nello script che hai utilizzato per fare le prove.
prendiamo il primo che hai postato. prima del casting ad intero, il risultato di
(4 - 1)*Rnd() + 1
può restituirti un numero "double" che va da 1 a 4
ora, se provi a fare il CInt di un numero double vedrai che:
CInt(1) = 1
CInt(1.49) = 1
CInt(1.51) = 2
CInt(2.49) = 2
CInt(2.51) = 3
CInt(3.49) = 3
CInt(3.51) = 4
CInt(4) = 4
è evidente che la probabilità di verificarsi di 1 e di 4 sono molto più basse di quelle di 2 e 3.
il tuo secondo script ha un problema fondato sulla medesima tecnica di arrotondamento.
ora prova questo:
codice:
<%
function upper(n)
dim ris
if CDbl(n) > fix(n) then
ris = Fix(n) +1
else
ris = Fix(n)
end if
upper = ris
end function
dim i, risultati(3), valore, numeri, elementiArr, frequenze
dim mDistr, mCamp
elementiArr = UBound(risultati)
for i=0 to elementi
risultati(i) = 0
next 'i
numeri = elementiArr +1
for i=1 to 10000
Randomize()
valore = upper(numeri * Rnd())
risultati(valore -1) = risultati(valore -1) +1
next 'i
mDistr = 0
mCamp = 0
frequenze = 0
for i=0 to elementiArr
Response.Write (CStr(i +1) & " freq. --> " & CStr(risultati(i)))
Response.Write ("
")
mDistr = mDistr + (i +1)
mCamp = mCamp + (i +1) * risultati(i)
frequenze = frequenze + risultati(i)
next 'i
Response.Write ("
Media Campionaria: " & CStr(CDbl(mCamp) / frequenze) )
Response.Write ("
Media della distribuzione: " & CStr(CDbl(mDistr) / (elementiArr +1)) )
%>
vedrai che i risultati confutano la legge dei grandi numeri (ossia che al crescere delle osservazioni la media campionaria tende alla media della distribuzione)

NB: anche il mio script ha un problema, nel senso che a causa dello zero la probabilità di verificarsi del primo numero della serie è leggermente più alta. per ottenere una perfetta equidistribuzione delle probabilità sarebbe sufficiente per esempio escludere le osservazioni dove rnd() restituisce zero