Verify distribution uniformity/Naive: Difference between revisions
Content deleted Content added
(15 intermediate revisions by 12 users not shown) | |||
Line 29:
{{trans|Python}}
<
R random:(1..5)
Line 41:
print(bin)
distcheck(dice5, 1000000, 1)</
{{out}}
Line 50:
=={{header|Ada}}==
<
procedure Naive_Random is
Line 100:
Ada.Text_IO.Put_Line("Test Passed? (" & Boolean'Image(OK) & ")");
end Naive_Random;</
Sample run 1 (all buckets good):<pre>7
Line 131:
=={{header|AutoHotkey}}==
<
DistCheck(function, repetitions, delta)
Line 153:
}
Return, text
}</
<pre>Distribution check:
Line 170:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<
FOR r% = 2 TO 5
check% = FNdistcheck(FNdice5, 10^r%, 0.05)
Line 196:
= s%
DEF FNdice5 = RND(5)</
Output:
<pre>
Line 206:
=={{header|C}}==
<
#include <stdio.h>
#include <math.h>
Line 251:
return 0;
}</
Count = 10: bin 1 out of range: 1 (-30% vs 3%), NOT flat
Count = 100: bin 1 out of range: 11 (-23% vs 3%), NOT flat
Line 259:
Count = 1000000: flat
</pre>
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
static void DistCheck(Func<int> func, int nRepeats, double delta)
{
var counts = new Dictionary<int, int>();
for (int i = 0; i < nRepeats; i++)
{
int result = func();
if (counts.ContainsKey(result))
counts[result]++;
else
counts[result] = 1;
}
double target = nRepeats / (double)counts.Count;
int deltaCount = (int)(delta / 100.0 * target);
foreach (var kvp in counts)
{
if (Math.Abs(target - kvp.Value) >= deltaCount)
Console.WriteLine("distribution potentially skewed for '{0}': '{1}'", kvp.Key, kvp.Value);
}
foreach (var key in counts.Keys.OrderBy(k => k))
{
Console.WriteLine("{0} {1}", key, counts[key]);
}
}
public static void Main(string[] args)
{
DistCheck(() => new Random().Next(1, 6), 1_000_000, 1);
}
}
</syntaxhighlight>
{{out}}
<pre>
1 200274
2 199430
3 199418
4 200473
5 200405
</pre>
=={{header|C++}}==
<
#include <iostream>
#include <cmath>
Line 291 ⟶ 345:
return good;
}</
=={{header|Clojure}}==
The code could be shortened if the verify function did the output itself, but the "Clojure way" is to have functions, whenever possible, avoid side effects (like printing) and just return a result. Then the "application-level" code uses doseq and println to display the output to the user. The built-in (rand-int) function is used for all three runs of the verify function, but first with small N to simulate experimental error in a small sample size, then with larger N to show it working properly on large N.
<
(let [rands (frequencies (repeatedly n rand))
avg (/ (reduce + (map val rands)) (count rands))
Line 306 ⟶ 360:
[num count okay?] (verify #(rand-int 7) n)]
(println "Saw" num count "times:"
(if okay? "that's" " not") "acceptable"))</
<pre>Saw 1 13 times: that's acceptable
Line 332 ⟶ 386:
=={{header|Common Lisp}}==
{{trans|OCaml}}
<
(let ((bins (make-hash-table)))
(loop repeat n do (incf (gethash (funcall function) bins 0)))
Line 340 ⟶ 394:
do (format t "~&Distribution potentially skewed for ~w:~
expected around ~w got ~w." key target value)
finally (return bins))))</
<pre>> (check-distribution 'd7 1000)
Line 355 ⟶ 409:
=={{header|D}}==
<
/**
Line 385 ⟶ 439:
distCheck(() => uniform(1, 6), 1_000_000, 1);
}
}</
If compiled with -version=verify_distribution_uniformity_naive_main:
{{out}}
Line 392 ⟶ 446:
4 200016
5 200424</pre>
=={{header|EasyLang}}==
<syntaxhighlight>
func dice5 .
return random 5
.
func dice25 .
return (dice5 - 1) * 5 + dice5
.
func dice7a .
return dice25 mod1 7
.
func dice7b .
repeat
h = dice25
until h <= 21
.
return h mod1 7
.
numfmt 3 0
#
proc checkdist dicefunc n delta . .
len dist[] 7
for i to n
# no function pointers
if dicefunc = 1
h = dice7a
else
h = dice7b
.
dist[h] += 1
.
for i to len dist[]
h = dist[i] / n * 7
if abs (h - 1) > delta
bad = 1
.
dist[i] = 0
print h
.
if bad = 1
print "-> not uniform"
else
print "-> uniform"
.
print ""
.
#
checkdist 1 1000000 0.01
checkdist 2 1000000 0.01
</syntaxhighlight>
{{out}}
<pre>
1.122
1.121
1.117
1.120
0.844
0.838
0.837
-> not uniform
0.997
1.000
1.004
1.001
0.997
1.001
1.000
-> uniform
</pre>
=={{header|Elixir}}==
{{trans|Erlang}}
<
def naive( generator, times, delta_percent ) do
dict = Enum.reduce( List.duplicate(generator, times), Map.new, &update_counter/2 )
Line 416 ⟶ 541:
fun = fn -> Dice.dice7 end
IO.inspect VerifyDistribution.naive( fun, 100000, 3 )
IO.inspect VerifyDistribution.naive( fun, 100, 3 )</
{{out}}
Line 427 ⟶ 552:
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
-module( verify_distribution_uniformity ).
Line 448 ⟶ 573:
update_counter( Fun, Dict ) -> dict:update_counter( Fun(), 1, Dict ).
</syntaxhighlight>
{{out}}
Line 466 ⟶ 591:
Following the task verbatim.
<syntaxhighlight lang="text">
>function checkrandom (frand$, n:index, delta:positive real) ...
$ v=zeros(1,n);
Line 482 ⟶ 607:
>checkrandom("wrongdice",1000000,1)
0
</syntaxhighlight>
Checking the dice7 from dice5 generator.
<syntaxhighlight lang="text">
>function dice5 () := intrandom(1,1,5);
>function dice7 () ...
Line 496 ⟶ 621:
>checkrandom("dice7",1000000,1)
1
</syntaxhighlight>
Faster implementation with the matrix language.
<syntaxhighlight lang="text">
>function dice5(n) := intrandom(1,n,5)-1;
>function dice7(n) ...
Line 519 ⟶ 644:
>checkrandom(wrongdice(1000000))
0
</syntaxhighlight>
=={{header|Factor}}==
<
math math.functions math.statistics math.vectors math.ranges ;
IN: rosetta-code.dice7
Line 578 ⟶ 703:
{ 1 10 100 1000 10000 100000 1000000 }
[| times | 0.02 7 [ dice7 ] times verify ] each
;</
Output:
Line 599 ⟶ 724:
=={{header|Forth}}==
requires Forth200x locals
<
: init-bins ( n -- addr )
cells dup allocate throw tuck swap erase ;
Line 622 ⟶ 747:
and
loop
bins free throw ;</
{{output}}
<pre>cr ' d7 1000000 7 1 check-distribution .
Line 648 ⟶ 773:
=={{header|Fortran}}==
{{works with|Fortran|95 and later}}
<
interface
Line 693 ⟶ 818:
deallocate(buckets)
end subroutine</
=={{header|FreeBASIC}}==
{{trans|Liberty BASIC}}
<syntaxhighlight lang="freebasic">
Randomize Timer
Function dice5() As Integer
Return Int(Rnd * 5) + 1
End Function
Function dice7() As Integer
Dim As Integer temp
Do
temp = dice5() * 5 + dice5() -6
Loop Until temp < 21
Return (temp Mod 7) +1
End Function
Function distCheck(n As Ulongint, delta As Double) As Ulongint
Dim As Ulongint a(n)
Dim As Ulongint maxBucket = 0
Dim As Ulongint minBucket = 1000000
For i As Ulongint = 1 To n
a(i) = dice5()
If a(i) > maxBucket Then maxBucket = a(i)
If a(i) < minBucket Then minBucket = a(i)
Next i
Dim As Ulongint nBuckets = maxBucket + 1
Dim As Ulongint buckets(maxBucket)
For i As Ulongint = 1 To n
buckets(a(i)) += 1
Next i
'check buckets
Dim As Ulongint expected = n / (maxBucket-minBucket+1)
Dim As Ulongint minVal = Int(expected*(1-delta))
Dim As Ulongint maxVal = Int(expected*(1+delta))
expected = Int(expected)
Print "minVal", "Expected", "maxVal"
Print minVal, expected, maxVal
Print "Bucket", "Counter", "pass/fail"
distCheck = true
For i As Ulongint = minBucket To maxBucket
Print i, buckets(i), Iif((minVal > buckets(i)) Or (buckets(i) > maxVal),"fail","")
If (minVal > buckets(i)) Or (buckets(i) > maxVal) Then Return false
Next i
End Function
Dim Shared As Ulongint n = 1000
Print "Testing ";n;" times"
If Not(distCheck(n, 0.05)) Then Print "Test failed" Else Print "Test passed"
Print
n = 10000
Print "Testing ";n;" times"
If Not(distCheck(n, 0.05)) Then Print "Test failed" Else Print "Test passed"
Print
n = 50000
Print "Testing ";n;" times"
If Not(distCheck(n, 0.05)) Then Print "Test failed" Else Print "Test passed"
Print
Sleep
</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de Liberty BASIC.
</pre>
=={{header|Go}}==
<
import (
Line 751 ⟶ 946:
max, flatEnough = distCheck(dice7, 7, calls, 500)
fmt.Println("Max delta:", max, "Flat enough:", flatEnough)
}</
Output:
<pre>
Line 759 ⟶ 954:
=={{header|Haskell}}==
<
import Data.List
import Control.Monad
Line 771 ⟶ 966:
ul = round $ (100 + fromIntegral d)/100 * avg
ll = round $ (100 - fromIntegral d)/100 * avg
return $ map (head &&& (id &&& liftM2 (&&) (>ll)(<ul)).length) group</
Example:
<
(1,(16911,True))
(2,(16599,True))
Line 779 ⟶ 974:
(4,(16624,True))
(5,(16526,True))
(6,(16670,True))</
=={{header|Hy}}==
<
(import [random [randint]])
Line 794 ⟶ 989:
(all (list-comp
(<= (- target delta) (/ n repeats) (+ target delta))
[n (.values bins)])))</
Examples of use:
<
(fn [] (randint 1 10))
(fn [] (if (randint 0 1) (randint 1 9) (randint 1 10)))]]
(print (uniform? f 5000 .02)))</
=={{header|Icon}} and {{header|Unicon}}==
This example assumes the random number generator is passed to <code>verify_uniform</code> as a co-expression. The co-expression <code>rnd</code> is prompted for its next value using <code>@rnd</code>. The co-expression is created using <code>create (|?10)</code> where the vertical bar means generate an infinite sequence of what is to its right (in this case, <code>?10</code> generates a random integer in the range [1,10]).
<
# n : the number of numbers to test
# delta: tolerance in non-uniformity
Line 835 ⟶ 1,030:
then write ("uniform")
else write ("skewed")
end</
Output:
<pre>
Line 866 ⟶ 1,061:
The ''delta'' is given as an optional left argument (<code>x</code>), defaulting to 5%. The right argument (<code>y</code>) is any valid argument to the distribution generating verb.
<
0.05 u checkUniform y
:
Line 877 ⟶ 1,072:
errmsg assert (delta * expected) > | expected - {:"1 freqtable
freqtable
)</
It is possible to use tacit expressions within an explicit definition enabling a more functional and concise style:
<
0.05 u checkUniformT y
:
Line 886 ⟶ 1,081:
errmsg assert ((n % #) (x&*@[ > |@:-) {:"1) freqtable
freqtable
)</
Show usage using <code>rollD7t</code> given in [[Seven-dice from Five-dice#J|Seven-dice from Five-dice]]:
<
1 14082
2 14337
Line 898 ⟶ 1,093:
0.05 rollD7t checkUniform 1e2
|Distribution is potentially skewed: assert
| errmsg assert(delta*expected)>|expected-{:"1 freqtable</
=={{header|Java}}==
{{trans|D}}
{{works with|Java|8}}
<
import java.util.*;
import java.util.function.IntSupplier;
Line 931 ⟶ 1,126:
distCheck(() -> (int) (Math.random() * 5) + 1, 1_000_000, 1);
}
}</
<pre>1 200439
2 201016
Line 940 ⟶ 1,135:
=={{header|JavaScript}}==
{{trans|Tcl}}
<
if (opts === undefined) opts = {}
opts['delta'] = opts['delta'] || 2;
Line 979 ⟶ 1,174:
} catch (e) {
print(e);
}</
Output:
<pre>0 9945
Line 995 ⟶ 1,190:
=={{header|Julia}}==
<
function distcheck(f::Function, rep::Int=10000, Δ::Int=3)
Line 1,011 ⟶ 1,206:
distcheck(x -> rand(1:5, x))
# Dice7 check
distcheck(dice7)</
=={{header|Kotlin}}==
<
import java.util.Random
Line 1,051 ⟶ 1,246:
println()
checkDist(::dice5, 100_000)
}</
Sample output:
Line 1,082 ⟶ 1,277:
=={{header|Liberty BASIC}}==
LB cannot pass user-defined function by name, so we use predefined function name - GENERATOR
<syntaxhighlight lang="lb">
n=1000
print "Testing ";n;" times"
Line 1,141 ⟶ 1,336:
GENERATOR = 1+int(rnd(0)*5) '1..5: dice5
end function
</syntaxhighlight>
{{Out}}
<pre>
Line 1,178 ⟶ 1,373:
</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
CheckDistribution[function_,number_,delta_] :=(Print["Expected: ", N[number/7], ", Generated :",
Transpose[Tally[Table[function, {number}]]][[2]] // Sort]; If[(Max[#]-Min[#])&
[Transpose[Tally[Table[function, {number}]]][[2]]] < delta*number/700, "Flat", "Skewed"])</
Example usage:
Line 1,196 ⟶ 1,391:
=={{header|Nim}}==
<
Line 1,223 ⟶ 1,418:
proc rand5(): int = rand(1..5)
checkDist(rand5, 1_000_000, 0.5)
</syntaxhighlight>
{{out}}
Line 1,231 ⟶ 1,426:
=={{header|OCaml}}==
<
let h = Hashtbl.create 5 in
for i = 1 to n do
Line 1,249 ⟶ 1,444:
key target value)
) h;
;;</
=={{header|PARI/GP}}==
This tests the purportedly random 7-sided die with a slightly biased 1000-sided die.
<
dice7()={
Line 1,282 ⟶ 1,477:
test(dice7, 10^5)
test(()->if(random(1000),random(1000),1), 10^5)</
Output:
<pre>Flat with significance 0.2931867820813680387842134664085280183
Line 1,291 ⟶ 1,486:
Testing two 'types' of 7-sided dice. Both appear to be fair.
{{trans|Raku}}
<
sub roll5 { 1+int rand(5) }
sub roll7_5 {
Line 1,320 ⟶ 1,515:
}
return $result . "\n";
}</
{{out}}
<pre> 143 expected
Line 1,359 ⟶ 1,554:
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">check</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">fid</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">range</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">iterations</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">delta</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- fid: routine_id of function that yields integer 1..range
-- range: the maximum value that is returned from fid
-- iterations: number of iterations to test
-- delta: variance, for example 0.005 means 0.5%
--
-- returns -1/0/1 for impossible/not flat/flat.
--</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">av</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">iterations</span><span style="color: #0000FF;">/</span><span style="color: #000000;">range</span> <span style="color: #000080;font-style:italic;">-- average/expected value</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">av</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">av</span><span style="color: #0000FF;">-</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">*</span><span style="color: #000000;">av</span>
<span style="color: #008080;">or</span> <span style="color: #7060A8;">ceil</span><span style="color: #0000FF;">(</span><span style="color: #000000;">av</span><span style="color: #0000FF;">)></span><span style="color: #000000;">av</span><span style="color: #0000FF;">+</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">*</span><span style="color: #000000;">av</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- impossible</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">counts</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">range</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">iterations</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">cdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fid</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">max_delta</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_abs</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">counts</span><span style="color: #0000FF;">,</span><span style="color: #000000;">av</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">max_delta</span><span style="color: #0000FF;"><</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">*</span><span style="color: #000000;">av</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">rand7</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">flats</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"impossible"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"not flat"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"flat"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">7</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- n = n+7-remainder(n,7)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">flat</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">check</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rand7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.005</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d iterations: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">flats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">flat</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,413 ⟶ 1,612:
(one-tenth of a percent), and a 'prg' code body (i.e. an arbitrary number of
executable expressions).
<
(let Res NIL
(do Cnt (accu 'Res (run Prg 1) 1))
Line 1,421 ⟶ 1,620:
Max (*/ N (+ 1000 Pm) 1000) )
(for R Res
(prinl (cdr R) " " (if (>= Max (cdr R) Min) "Good" "Bad")) ) ) ) )</
Output:
<pre>: (checkDistribution 100000 5 (rand 1 7))
Line 1,433 ⟶ 1,632:
=={{header|PureBasic}}==
<
Procedure.s distcheck(*function.RandNum_prt, repetitions, delta.d)
Line 1,463 ⟶ 1,662:
EndProcedure
MessageRequester("Results", distcheck(@dice7(), 1000000, 0.20))</
A small delta was chosen to increase the chance of a skewed result in the sample output:
<pre>Distribution check:
Line 1,476 ⟶ 1,675:
=={{header|Python}}==
{{works with|Python|3.1}}
<
from pprint import pprint as pp
Line 1,491 ⟶ 1,690:
for key, count in sorted(bin.items()) ]
)
pp(dict(bin))</
Sample output:
<pre>>>> distcheck(dice5, 1000000, 1)
Line 1,502 ⟶ 1,701:
for key, count in sorted(bin.items()) ]
AssertionError: Bin distribution skewed from 200 +/- 2: [(1, 4), (2, -33), (3, 6), (4, 11), (5, 12)]</pre>
=={{header|Quackery}}==
The word <code>distribution</code> tests a specified word (Quackery function) which should return numbers in the range 1 to 7 inclusive. The word <code>dice7</code>, which satisfies this requirement, is defined at [[Seven-sided dice from five-sided dice#Quackery]].
<syntaxhighlight lang="quackery"> [ stack [ 0 0 0 0 0 0 0 ] ] is bins ( --> s )
[ 7 times
[ 0 bins take
i poke
bins put ] ] is emptybins ( --> )
[ bins share over peek
1+ bins take rot poke
bins put ] is bincrement ( n --> )
[ emptybins
over 7 / temp put
swap times
[ over do 1 -
bincrement ]
bins share dup echo cr
witheach
[ temp share - abs
over > if
[ say "Number of "
i^ 1+ echo
say "s is sketchy."
cr ] ]
2drop temp release ] is distribution ( x n n --> )</syntaxhighlight>
{{out}}
Testing in the Quackery shell.
<pre>/O> ' dice7 1000 20 distribution
...
[ 131 123 160 144 156 145 141 ]
Stack empty.
/O> ' dice7 1000 10 distribution
...
[ 137 138 130 160 143 150 142 ]
Number of 3s is sketchy.
Number of 4s is sketchy.
</pre>
=={{header|R}}==
<
{
if(is.character(fn))
Line 1,523 ⟶ 1,769:
data.frame(value=names(counts), counts=as.vector(counts), status=status)
}
distcheck(dice7.vec)</
=={{header|Racket}}==
Line 1,530 ⟶ 1,776:
Returns a pair of a boolean stating uniformity and either the "uniform" distribution or a report of the first skew number found.
<
(define (pretty-fraction f)
(if (integer? f) f
Line 1,566 ⟶ 1,812:
(test-uniformity/naive straight-die 1000 5)
; Test whether a biased die fails:
(test-uniformity/naive crooked-die 1000 5)</
{{out}}
Line 1,576 ⟶ 1,822:
(formerly Perl 6)
Since the tested function is rolls of a 7 sided die, the test numbers are magnitudes of 10<sup>x</sup> bumped up to the closest multiple of 7. This reduces spurious error from there not being an integer expected value.
<syntaxhighlight lang="raku"
sub roll7 { $d7.roll };
Line 1,600 ⟶ 1,846:
}
say '';
}</
Sample output:
<pre>
Line 1,659 ⟶ 1,905:
=={{header|REXX}}==
<
parse arg func times delta seed . /*obtain arguments (options) from C.L. */
if func=='' | func=="," then func= 'RANDOM' /*function not specified? Use default.*/
if times=='' | times=="," then times= 1000000 /*times " " " " */
if delta=='' | delta=="," then
if datatype(seed, 'W') then call random ,,seed /*use some RAND seed for repeatability.*/
highDig=
!.=
do times /* [↓] perform a bunch of trials. */
if func=='RANDOM' then ?= random(highDig) /*use RANDOM function.*/
else interpret '?=' func "(0,"highDig')' /* " specified " */
!.?= !.? + 1 /*bump the invocation counter.*/
end /*
/* [↓] compute the digit's skewness. */
g= times / (1 + highDig) /*calculate number of each digit throw.*/
Line 1,677 ⟶ 1,923:
pad= left('', 9) /*this is used for output indentation. */
say pad 'digit' center(" hits", w) ' skew ' "skew %" 'result' /*header. */
say sep /*display a separator line. */
/** [↑] show header and the separator.*/
do k=0 to highDig
skew= g - !.k
skewPC= (1 - (g - abs(skew)) / g) * 100
say pad center(k, 5)
right( format(skewPC, , 3), 6)
end /*k*/
say sep /*display a separator line. */
y= 5+1+w+1+6+1+6+1+6 /*width + seps*/
say pad center(" (with " commas(times) ' trials)' , y) /*# trials. */
say pad center(" (skewed when exceeds " delta'%)' , y) /*skewed note.*/
exit
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg _; do jc=length(_)-3 to 1 by -3; _=insert(',', _, jc); end; return _
sep: say pad '─────' center('', w, '─') '──────' "──────" '──────'; return</syntaxhighlight>
{{out|output|text= when using the default inputs:}}
<pre>
Line 1,713 ⟶ 1,959:
=={{header|Ring}}==
<
# Project : Verify distribution uniformity/Naive
Line 1,744 ⟶ 1,990:
func dice5
return random(5)
</syntaxhighlight>
Output:
<pre>
Line 1,751 ⟶ 1,997:
Over 10000 runs dice5 passed distribution check
Over 100000 runs dice5 passed distribution check
</pre>
=={{header|RPL}}==
Calculated frequencies are negative when below/above the tolerance given by <code>delta</code>.
<code>DICE7</code> is defined at [[Seven-sided dice from five-sided dice#RPL|Seven-sided dice from five-sided dice]]
≪ 1 → func n delta bins
≪ { 1 } 0 CON
1 n '''FOR''' j
func EVAL
'''IF''' bins OVER < '''THEN'''
DUP 'bins' STO
1 →LIST RDM bins
'''END'''
DUP2 GET 1 + PUT
'''NEXT'''
1 bins '''FOR''' j
DUP j GET
'''IF'''
DUP n bins / %CH 100 / ABS
delta >
'''THEN''' NEG j SWAP PUT '''ELSE''' DROP '''END'''
'''NEXT'''
≫ ≫ '<span style="color:blue">UNIF?</span>' STO
≪ <span style="color:blue">DICE7</span> ≫ 10000 .05 <span style="color:blue">UNIF?</span>
≪ 6 RAND * CEIL ≫ 1000 .05 <span style="color:blue">UNIF?</span>
{{out}}
<pre>
2: [ 1439 1404 1413 1410 1424 1486 1424 ]
1: [ 169 172 -158 163 171 167 ]
</pre>
=={{header|Ruby}}==
{{trans|Tcl}}
<
unless block_given?
raise ArgumentError, "pass a block to this method"
Line 1,781 ⟶ 2,058:
p e
end
end</
{{out}}
Line 1,798 ⟶ 2,075:
=={{header|Run BASIC}}==
<
dim num(100)
for i = 1 to 1000
Line 1,807 ⟶ 2,084:
for i = 1 to 10
print using("###",i);" "; using("#####",num(i));" ";left$(s$,num(i) / 5)
next i</
1 90 ##################
2 110 ######################
Line 1,821 ⟶ 2,098:
=={{header|Scala}}==
===Imperative, ugly, mutable data===
<
private def distCheck(f: () => Int, nRepeats: Int, delta: Double): Unit = {
Line 1,844 ⟶ 2,121:
distCheck(() => 1 + util.Random.nextInt(5), 1_000_000, 1)
}</
===Functional Style===
{{Out}}Best seen running in your browser either by [https://scalafiddle.io/sf/oYJWUvX/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/O513W3VoQ7ulspUMnGvTiQ Scastie (remote JVM)].
<
private def distCheck(f: () => Int, nRepeats: Int, delta: Double): Unit = {
val counts: Map[Int, Int] =
Line 1,862 ⟶ 2,139:
distCheck(() => 1 + util.Random.nextInt(5), 1_000_000, 1)
}</
=={{header|Tcl}}==
<
for {set i 0} {$i<$times} {incr i} {incr vals([uplevel 1 $random])}
set target [expr {$times / [array size vals]}]
Line 1,875 ⟶ 2,152:
foreach k [lsort -integer [array names vals]] {lappend result $k $vals($k)}
return $result
}</
Demonstration:
<
puts [distcheck {expr {int(10*rand())}} 100000]
# Now, one that definitely isn't!
puts [distcheck {expr {rand()>0.95}} 100000]</
Which produces this output (error in red):
0 10003 1 9851 2 10058 3 10193 4 10126 5 10002 6 9852 7 9964 8 9957 9 9994
Line 1,887 ⟶ 2,164:
=={{header|VBScript}}==
<
sub verifydistribution(calledfunction, samples, delta)
Line 1,910 ⟶ 2,187:
& ", desired limit is " & FormatPercent(delta, 2) & "."
if maxdiff > delta then wscript.echo "Skewed!" else wscript.echo "Smooth!"
end sub</
Demonstration with included [[Seven-sided dice from five-sided dice#VBScript]] code:
<
verifydistribution "dice7", 100000, 0.03</
Which produces this output:
Running "dice7" 1000 times...
Line 1,937 ⟶ 2,214:
Maximum found variation is 0.94%, desired limit is 3.00%.
Smooth!
=={{header|V (Vlang)}}==
{{trans|go}}
<syntaxhighlight lang="v (vlang)">import rand
import rand.seed
import math
// "given"
fn dice5() int {
return rand.intn(5) or {0} + 1
}
// fntion specified by task "Seven-sided dice from five-sided dice"
fn dice7() int {
mut i := 0
for {
i = 5*dice5() + dice5()
if i < 27 {
break
}
}
return (i / 3) - 1
}
// fntion specified by task "Verify distribution uniformity/Naive"
//
// Parameter "f" is expected to return a random integer in the range 1..n.
// (Values out of range will cause an unceremonious crash.)
// "Max" is returned as an "indication of distribution achieved."
// It is the maximum delta observed from the count representing a perfectly
// uniform distribution.
// Also returned is a boolean, true if "max" is less than threshold
// parameter "delta."
fn dist_check(f fn() int, n int,
repeats int, delta f64) (f64, bool) {
mut max := 0.0
mut count := []int{len: n}
for _ in 0..repeats {
count[f()-1]++
}
expected := f64(repeats) / f64(n)
for c in count {
max = math.max(max, math.abs(f64(c)-expected))
}
return max, max < delta
}
// Driver, produces output satisfying both tasks.
fn main() {
rand.seed(seed.time_seed_array(2))
calls := 1000000
mut max, mut flat_enough := dist_check(dice7, 7, calls, 500)
println("Max delta: $max Flat enough: $flat_enough")
max, flat_enough = dist_check(dice7, 7, calls, 500)
println("Max delta: $max Flat enough: $flat_enough")
}</syntaxhighlight>
{{out}}
<pre>
Max delta: 723.8571428571304 Flat enough: false
Max delta: 435.1428571428696 Flat enough: true
</pre>
=={{header|Wren}}==
Line 1,942 ⟶ 2,279:
{{libheader|Wren-fmt}}
{{libheader|Wren-sort}}
<
import "./fmt" for Fmt
import "./sort" for Sort
var r = Random.new()
Line 1,976 ⟶ 2,313:
checkDist.call(dice5, 1e6, 0.5)
System.print()
checkDist.call(dice5, 1e5, 0.5)</
{{out}}
Line 2,008 ⟶ 2,345:
=={{header|zkl}}==
This tests the random spread over 0..9. It starts at 10 samples and doubles the sample size until the spread is within 0.1% of 10% for each bucket.
<
dist:=L(0,0,0,0,0,0,0,0,0,0);
do(N){n:=(0).random(10); dist[n]=dist[n]+1}
Line 2,019 ⟶ 2,356:
n:=10;
while(not rtest(n)) {n*=2}</
{{out}}
Reported numbers is the percent that bucket has of all samples.
|