Verify distribution uniformity/Naive: Difference between revisions
Content added Content deleted
No edit summary |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 29: | Line 29: | ||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="11l">F dice5() |
||
R random:(1..5) |
R random:(1..5) |
||
Line 41: | Line 41: | ||
print(bin) |
print(bin) |
||
distcheck(dice5, 1000000, 1)</ |
distcheck(dice5, 1000000, 1)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 50: | Line 50: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Numerics.Discrete_Random, Ada.Text_IO; |
||
procedure Naive_Random is |
procedure Naive_Random is |
||
Line 100: | Line 100: | ||
Ada.Text_IO.Put_Line("Test Passed? (" & Boolean'Image(OK) & ")"); |
Ada.Text_IO.Put_Line("Test Passed? (" & Boolean'Image(OK) & ")"); |
||
end Naive_Random;</ |
end Naive_Random;</syntaxhighlight> |
||
Sample run 1 (all buckets good):<pre>7 |
Sample run 1 (all buckets good):<pre>7 |
||
Line 131: | Line 131: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="autohotkey">MsgBox, % DistCheck("dice7",10000,3) |
||
DistCheck(function, repetitions, delta) |
DistCheck(function, repetitions, delta) |
||
Line 153: | Line 153: | ||
} |
} |
||
Return, text |
Return, text |
||
}</ |
}</syntaxhighlight> |
||
<pre>Distribution check: |
<pre>Distribution check: |
||
Line 170: | Line 170: | ||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
{{works with|BBC BASIC for Windows}} |
{{works with|BBC BASIC for Windows}} |
||
< |
<syntaxhighlight lang="bbcbasic"> MAXRND = 7 |
||
FOR r% = 2 TO 5 |
FOR r% = 2 TO 5 |
||
check% = FNdistcheck(FNdice5, 10^r%, 0.05) |
check% = FNdistcheck(FNdice5, 10^r%, 0.05) |
||
Line 196: | Line 196: | ||
= s% |
= s% |
||
DEF FNdice5 = RND(5)</ |
DEF FNdice5 = RND(5)</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 206: | Line 206: | ||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">#include <stdlib.h> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <math.h> |
#include <math.h> |
||
Line 251: | Line 251: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight>output<pre> |
||
Count = 10: bin 1 out of range: 1 (-30% vs 3%), NOT flat |
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 |
Count = 100: bin 1 out of range: 11 (-23% vs 3%), NOT flat |
||
Line 261: | Line 261: | ||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp">#include <map> |
||
#include <iostream> |
#include <iostream> |
||
#include <cmath> |
#include <cmath> |
||
Line 291: | Line 291: | ||
return good; |
return good; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Clojure}}== |
=={{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. |
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. |
||
< |
<syntaxhighlight lang="clojure">(defn verify [rand n & [delta]] |
||
(let [rands (frequencies (repeatedly n rand)) |
(let [rands (frequencies (repeatedly n rand)) |
||
avg (/ (reduce + (map val rands)) (count rands)) |
avg (/ (reduce + (map val rands)) (count rands)) |
||
Line 306: | Line 306: | ||
[num count okay?] (verify #(rand-int 7) n)] |
[num count okay?] (verify #(rand-int 7) n)] |
||
(println "Saw" num count "times:" |
(println "Saw" num count "times:" |
||
(if okay? "that's" " not") "acceptable"))</ |
(if okay? "that's" " not") "acceptable"))</syntaxhighlight> |
||
<pre>Saw 1 13 times: that's acceptable |
<pre>Saw 1 13 times: that's acceptable |
||
Line 332: | Line 332: | ||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
{{trans|OCaml}} |
{{trans|OCaml}} |
||
< |
<syntaxhighlight lang="lisp">(defun check-distribution (function n &optional (delta 1.0)) |
||
(let ((bins (make-hash-table))) |
(let ((bins (make-hash-table))) |
||
(loop repeat n do (incf (gethash (funcall function) bins 0))) |
(loop repeat n do (incf (gethash (funcall function) bins 0))) |
||
Line 340: | Line 340: | ||
do (format t "~&Distribution potentially skewed for ~w:~ |
do (format t "~&Distribution potentially skewed for ~w:~ |
||
expected around ~w got ~w." key target value) |
expected around ~w got ~w." key target value) |
||
finally (return bins))))</ |
finally (return bins))))</syntaxhighlight> |
||
<pre>> (check-distribution 'd7 1000) |
<pre>> (check-distribution 'd7 1000) |
||
Line 355: | Line 355: | ||
=={{header|D}}== |
=={{header|D}}== |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.string, std.math, std.algorithm, std.traits; |
||
/** |
/** |
||
Line 385: | Line 385: | ||
distCheck(() => uniform(1, 6), 1_000_000, 1); |
distCheck(() => uniform(1, 6), 1_000_000, 1); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
If compiled with -version=verify_distribution_uniformity_naive_main: |
If compiled with -version=verify_distribution_uniformity_naive_main: |
||
{{out}} |
{{out}} |
||
Line 395: | Line 395: | ||
=={{header|Elixir}}== |
=={{header|Elixir}}== |
||
{{trans|Erlang}} |
{{trans|Erlang}} |
||
< |
<syntaxhighlight lang="elixir">defmodule VerifyDistribution do |
||
def naive( generator, times, delta_percent ) do |
def naive( generator, times, delta_percent ) do |
||
dict = Enum.reduce( List.duplicate(generator, times), Map.new, &update_counter/2 ) |
dict = Enum.reduce( List.duplicate(generator, times), Map.new, &update_counter/2 ) |
||
Line 416: | Line 416: | ||
fun = fn -> Dice.dice7 end |
fun = fn -> Dice.dice7 end |
||
IO.inspect VerifyDistribution.naive( fun, 100000, 3 ) |
IO.inspect VerifyDistribution.naive( fun, 100000, 3 ) |
||
IO.inspect VerifyDistribution.naive( fun, 100, 3 )</ |
IO.inspect VerifyDistribution.naive( fun, 100, 3 )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 427: | Line 427: | ||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
<syntaxhighlight lang="erlang"> |
|||
<lang Erlang> |
|||
-module( verify_distribution_uniformity ). |
-module( verify_distribution_uniformity ). |
||
Line 448: | Line 448: | ||
update_counter( Fun, Dict ) -> dict:update_counter( Fun(), 1, Dict ). |
update_counter( Fun, Dict ) -> dict:update_counter( Fun(), 1, Dict ). |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 466: | Line 466: | ||
Following the task verbatim. |
Following the task verbatim. |
||
<lang> |
<syntaxhighlight lang="text"> |
||
>function checkrandom (frand$, n:index, delta:positive real) ... |
>function checkrandom (frand$, n:index, delta:positive real) ... |
||
$ v=zeros(1,n); |
$ v=zeros(1,n); |
||
Line 482: | Line 482: | ||
>checkrandom("wrongdice",1000000,1) |
>checkrandom("wrongdice",1000000,1) |
||
0 |
0 |
||
</syntaxhighlight> |
|||
</lang> |
|||
Checking the dice7 from dice5 generator. |
Checking the dice7 from dice5 generator. |
||
<lang> |
<syntaxhighlight lang="text"> |
||
>function dice5 () := intrandom(1,1,5); |
>function dice5 () := intrandom(1,1,5); |
||
>function dice7 () ... |
>function dice7 () ... |
||
Line 496: | Line 496: | ||
>checkrandom("dice7",1000000,1) |
>checkrandom("dice7",1000000,1) |
||
1 |
1 |
||
</syntaxhighlight> |
|||
</lang> |
|||
Faster implementation with the matrix language. |
Faster implementation with the matrix language. |
||
<lang> |
<syntaxhighlight lang="text"> |
||
>function dice5(n) := intrandom(1,n,5)-1; |
>function dice5(n) := intrandom(1,n,5)-1; |
||
>function dice7(n) ... |
>function dice7(n) ... |
||
Line 519: | Line 519: | ||
>checkrandom(wrongdice(1000000)) |
>checkrandom(wrongdice(1000000)) |
||
0 |
0 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
< |
<syntaxhighlight lang="factor">USING: kernel random sequences assocs locals sorting prettyprint |
||
math math.functions math.statistics math.vectors math.ranges ; |
math math.functions math.statistics math.vectors math.ranges ; |
||
IN: rosetta-code.dice7 |
IN: rosetta-code.dice7 |
||
Line 578: | Line 578: | ||
{ 1 10 100 1000 10000 100000 1000000 } |
{ 1 10 100 1000 10000 100000 1000000 } |
||
[| times | 0.02 7 [ dice7 ] times verify ] each |
[| times | 0.02 7 [ dice7 ] times verify ] each |
||
;</ |
;</syntaxhighlight> |
||
Output: |
Output: |
||
Line 599: | Line 599: | ||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
requires Forth200x locals |
requires Forth200x locals |
||
< |
<syntaxhighlight lang="forth">: .bounds ( u1 u2 -- ) ." lower bound = " . ." upper bound = " 1- . cr ; |
||
: init-bins ( n -- addr ) |
: init-bins ( n -- addr ) |
||
cells dup allocate throw tuck swap erase ; |
cells dup allocate throw tuck swap erase ; |
||
Line 622: | Line 622: | ||
and |
and |
||
loop |
loop |
||
bins free throw ;</ |
bins free throw ;</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
<pre>cr ' d7 1000000 7 1 check-distribution . |
<pre>cr ' d7 1000000 7 1 check-distribution . |
||
Line 648: | Line 648: | ||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
{{works with|Fortran|95 and later}} |
{{works with|Fortran|95 and later}} |
||
< |
<syntaxhighlight lang="fortran">subroutine distcheck(randgen, n, delta) |
||
interface |
interface |
||
Line 693: | Line 693: | ||
deallocate(buckets) |
deallocate(buckets) |
||
end subroutine</ |
end subroutine</syntaxhighlight> |
||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
{{trans|Liberty BASIC}} |
{{trans|Liberty BASIC}} |
||
< |
<syntaxhighlight lang="freebasic"> |
||
Randomize Timer |
Randomize Timer |
||
Function dice5() As Integer |
Function dice5() As Integer |
||
Line 758: | Line 758: | ||
Print |
Print |
||
Sleep |
Sleep |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 766: | Line 766: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 821: | Line 821: | ||
max, flatEnough = distCheck(dice7, 7, calls, 500) |
max, flatEnough = distCheck(dice7, 7, calls, 500) |
||
fmt.Println("Max delta:", max, "Flat enough:", flatEnough) |
fmt.Println("Max delta:", max, "Flat enough:", flatEnough) |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 829: | Line 829: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang="haskell">import System.Random |
||
import Data.List |
import Data.List |
||
import Control.Monad |
import Control.Monad |
||
Line 841: | Line 841: | ||
ul = round $ (100 + fromIntegral d)/100 * avg |
ul = round $ (100 + fromIntegral d)/100 * avg |
||
ll = round $ (100 - fromIntegral d)/100 * avg |
ll = round $ (100 - fromIntegral d)/100 * avg |
||
return $ map (head &&& (id &&& liftM2 (&&) (>ll)(<ul)).length) group</ |
return $ map (head &&& (id &&& liftM2 (&&) (>ll)(<ul)).length) group</syntaxhighlight> |
||
Example: |
Example: |
||
< |
<syntaxhighlight lang="haskell">*Main> mapM_ print .sort =<< distribCheck (randomRIO(1,6)) 100000 3 |
||
(1,(16911,True)) |
(1,(16911,True)) |
||
(2,(16599,True)) |
(2,(16599,True)) |
||
Line 849: | Line 849: | ||
(4,(16624,True)) |
(4,(16624,True)) |
||
(5,(16526,True)) |
(5,(16526,True)) |
||
(6,(16670,True))</ |
(6,(16670,True))</syntaxhighlight> |
||
=={{header|Hy}}== |
=={{header|Hy}}== |
||
< |
<syntaxhighlight lang="lisp">(import [collections [Counter]]) |
||
(import [random [randint]]) |
(import [random [randint]]) |
||
Line 864: | Line 864: | ||
(all (list-comp |
(all (list-comp |
||
(<= (- target delta) (/ n repeats) (+ target delta)) |
(<= (- target delta) (/ n repeats) (+ target delta)) |
||
[n (.values bins)])))</ |
[n (.values bins)])))</syntaxhighlight> |
||
Examples of use: |
Examples of use: |
||
< |
<syntaxhighlight lang="lisp">(for [f [ |
||
(fn [] (randint 1 10)) |
(fn [] (randint 1 10)) |
||
(fn [] (if (randint 0 1) (randint 1 9) (randint 1 10)))]] |
(fn [] (if (randint 0 1) (randint 1 9) (randint 1 10)))]] |
||
(print (uniform? f 5000 .02)))</ |
(print (uniform? f 5000 .02)))</syntaxhighlight> |
||
=={{header|Icon}} and {{header|Unicon}}== |
=={{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]). |
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]). |
||
< |
<syntaxhighlight lang="icon"># rnd : a co-expression, which will generate the random numbers |
||
# n : the number of numbers to test |
# n : the number of numbers to test |
||
# delta: tolerance in non-uniformity |
# delta: tolerance in non-uniformity |
||
Line 905: | Line 905: | ||
then write ("uniform") |
then write ("uniform") |
||
else write ("skewed") |
else write ("skewed") |
||
end</ |
end</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 936: | Line 936: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="j">checkUniform=: adverb define |
||
0.05 u checkUniform y |
0.05 u checkUniform y |
||
: |
: |
||
Line 947: | Line 947: | ||
errmsg assert (delta * expected) > | expected - {:"1 freqtable |
errmsg assert (delta * expected) > | expected - {:"1 freqtable |
||
freqtable |
freqtable |
||
)</ |
)</syntaxhighlight> |
||
It is possible to use tacit expressions within an explicit definition enabling a more functional and concise style: |
It is possible to use tacit expressions within an explicit definition enabling a more functional and concise style: |
||
< |
<syntaxhighlight lang="j">checkUniformT=: adverb define |
||
0.05 u checkUniformT y |
0.05 u checkUniformT y |
||
: |
: |
||
Line 956: | Line 956: | ||
errmsg assert ((n % #) (x&*@[ > |@:-) {:"1) freqtable |
errmsg assert ((n % #) (x&*@[ > |@:-) {:"1) freqtable |
||
freqtable |
freqtable |
||
)</ |
)</syntaxhighlight> |
||
Show usage using <code>rollD7t</code> given in [[Seven-dice from Five-dice#J|Seven-dice from Five-dice]]: |
Show usage using <code>rollD7t</code> given in [[Seven-dice from Five-dice#J|Seven-dice from Five-dice]]: |
||
< |
<syntaxhighlight lang="j"> 0.05 rollD7t checkUniform 1e5 |
||
1 14082 |
1 14082 |
||
2 14337 |
2 14337 |
||
Line 968: | Line 968: | ||
0.05 rollD7t checkUniform 1e2 |
0.05 rollD7t checkUniform 1e2 |
||
|Distribution is potentially skewed: assert |
|Distribution is potentially skewed: assert |
||
| errmsg assert(delta*expected)>|expected-{:"1 freqtable</ |
| errmsg assert(delta*expected)>|expected-{:"1 freqtable</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{trans|D}} |
{{trans|D}} |
||
{{works with|Java|8}} |
{{works with|Java|8}} |
||
< |
<syntaxhighlight lang="java">import static java.lang.Math.abs; |
||
import java.util.*; |
import java.util.*; |
||
import java.util.function.IntSupplier; |
import java.util.function.IntSupplier; |
||
Line 1,001: | Line 1,001: | ||
distCheck(() -> (int) (Math.random() * 5) + 1, 1_000_000, 1); |
distCheck(() -> (int) (Math.random() * 5) + 1, 1_000_000, 1); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
<pre>1 200439 |
<pre>1 200439 |
||
2 201016 |
2 201016 |
||
Line 1,010: | Line 1,010: | ||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
{{trans|Tcl}} |
{{trans|Tcl}} |
||
< |
<syntaxhighlight lang="javascript">function distcheck(random_func, times, opts) { |
||
if (opts === undefined) opts = {} |
if (opts === undefined) opts = {} |
||
opts['delta'] = opts['delta'] || 2; |
opts['delta'] = opts['delta'] || 2; |
||
Line 1,049: | Line 1,049: | ||
} catch (e) { |
} catch (e) { |
||
print(e); |
print(e); |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>0 9945 |
<pre>0 9945 |
||
Line 1,065: | Line 1,065: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">using Printf |
||
function distcheck(f::Function, rep::Int=10000, Δ::Int=3) |
function distcheck(f::Function, rep::Int=10000, Δ::Int=3) |
||
Line 1,081: | Line 1,081: | ||
distcheck(x -> rand(1:5, x)) |
distcheck(x -> rand(1:5, x)) |
||
# Dice7 check |
# Dice7 check |
||
distcheck(dice7)</ |
distcheck(dice7)</syntaxhighlight> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
< |
<syntaxhighlight lang="scala">// version 1.1.3 |
||
import java.util.Random |
import java.util.Random |
||
Line 1,121: | Line 1,121: | ||
println() |
println() |
||
checkDist(::dice5, 100_000) |
checkDist(::dice5, 100_000) |
||
}</ |
}</syntaxhighlight> |
||
Sample output: |
Sample output: |
||
Line 1,152: | Line 1,152: | ||
=={{header|Liberty BASIC}}== |
=={{header|Liberty BASIC}}== |
||
LB cannot pass user-defined function by name, so we use predefined function name - GENERATOR |
LB cannot pass user-defined function by name, so we use predefined function name - GENERATOR |
||
<syntaxhighlight lang="lb"> |
|||
<lang lb> |
|||
n=1000 |
n=1000 |
||
print "Testing ";n;" times" |
print "Testing ";n;" times" |
||
Line 1,211: | Line 1,211: | ||
GENERATOR = 1+int(rnd(0)*5) '1..5: dice5 |
GENERATOR = 1+int(rnd(0)*5) '1..5: dice5 |
||
end function |
end function |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Out}} |
{{Out}} |
||
<pre> |
<pre> |
||
Line 1,249: | Line 1,249: | ||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">SetAttributes[CheckDistribution, HoldFirst] |
||
CheckDistribution[function_,number_,delta_] :=(Print["Expected: ", N[number/7], ", Generated :", |
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]] // Sort]; If[(Max[#]-Min[#])& |
||
[Transpose[Tally[Table[function, {number}]]][[2]]] < delta*number/700, "Flat", "Skewed"])</ |
[Transpose[Tally[Table[function, {number}]]][[2]]] < delta*number/700, "Flat", "Skewed"])</syntaxhighlight> |
||
Example usage: |
Example usage: |
||
Line 1,266: | Line 1,266: | ||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
< |
<syntaxhighlight lang="nim">import tables |
||
Line 1,293: | Line 1,293: | ||
proc rand5(): int = rand(1..5) |
proc rand5(): int = rand(1..5) |
||
checkDist(rand5, 1_000_000, 0.5) |
checkDist(rand5, 1_000_000, 0.5) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 1,301: | Line 1,301: | ||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
< |
<syntaxhighlight lang="ocaml">let distcheck fn n ?(delta=1.0) () = |
||
let h = Hashtbl.create 5 in |
let h = Hashtbl.create 5 in |
||
for i = 1 to n do |
for i = 1 to n do |
||
Line 1,319: | Line 1,319: | ||
key target value) |
key target value) |
||
) h; |
) h; |
||
;;</ |
;;</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
This tests the purportedly random 7-sided die with a slightly biased 1000-sided die. |
This tests the purportedly random 7-sided die with a slightly biased 1000-sided die. |
||
< |
<syntaxhighlight lang="parigp">dice5()=random(5)+1; |
||
dice7()={ |
dice7()={ |
||
Line 1,352: | Line 1,352: | ||
test(dice7, 10^5) |
test(dice7, 10^5) |
||
test(()->if(random(1000),random(1000),1), 10^5)</ |
test(()->if(random(1000),random(1000),1), 10^5)</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>Flat with significance 0.2931867820813680387842134664085280183 |
<pre>Flat with significance 0.2931867820813680387842134664085280183 |
||
Line 1,361: | Line 1,361: | ||
Testing two 'types' of 7-sided dice. Both appear to be fair. |
Testing two 'types' of 7-sided dice. Both appear to be fair. |
||
{{trans|Raku}} |
{{trans|Raku}} |
||
< |
<syntaxhighlight lang="perl">sub roll7 { 1+int rand(7) } |
||
sub roll5 { 1+int rand(5) } |
sub roll5 { 1+int rand(5) } |
||
sub roll7_5 { |
sub roll7_5 { |
||
Line 1,390: | Line 1,390: | ||
} |
} |
||
return $result . "\n"; |
return $result . "\n"; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> 143 expected |
<pre> 143 expected |
||
Line 1,429: | Line 1,429: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<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: #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> |
||
Line 1,466: | Line 1,466: | ||
<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: #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> |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,487: | Line 1,487: | ||
(one-tenth of a percent), and a 'prg' code body (i.e. an arbitrary number of |
(one-tenth of a percent), and a 'prg' code body (i.e. an arbitrary number of |
||
executable expressions). |
executable expressions). |
||
< |
<syntaxhighlight lang="picolisp">(de checkDistribution (Cnt Pm . Prg) |
||
(let Res NIL |
(let Res NIL |
||
(do Cnt (accu 'Res (run Prg 1) 1)) |
(do Cnt (accu 'Res (run Prg 1) 1)) |
||
Line 1,495: | Line 1,495: | ||
Max (*/ N (+ 1000 Pm) 1000) ) |
Max (*/ N (+ 1000 Pm) 1000) ) |
||
(for R Res |
(for R Res |
||
(prinl (cdr R) " " (if (>= Max (cdr R) Min) "Good" "Bad")) ) ) ) )</ |
(prinl (cdr R) " " (if (>= Max (cdr R) Min) "Good" "Bad")) ) ) ) )</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>: (checkDistribution 100000 5 (rand 1 7)) |
<pre>: (checkDistribution 100000 5 (rand 1 7)) |
||
Line 1,507: | Line 1,507: | ||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
< |
<syntaxhighlight lang="purebasic">Prototype RandNum_prt() |
||
Procedure.s distcheck(*function.RandNum_prt, repetitions, delta.d) |
Procedure.s distcheck(*function.RandNum_prt, repetitions, delta.d) |
||
Line 1,537: | Line 1,537: | ||
EndProcedure |
EndProcedure |
||
MessageRequester("Results", distcheck(@dice7(), 1000000, 0.20))</ |
MessageRequester("Results", distcheck(@dice7(), 1000000, 0.20))</syntaxhighlight> |
||
A small delta was chosen to increase the chance of a skewed result in the sample output: |
A small delta was chosen to increase the chance of a skewed result in the sample output: |
||
<pre>Distribution check: |
<pre>Distribution check: |
||
Line 1,550: | Line 1,550: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{works with|Python|3.1}} |
{{works with|Python|3.1}} |
||
< |
<syntaxhighlight lang="python">from collections import Counter |
||
from pprint import pprint as pp |
from pprint import pprint as pp |
||
Line 1,565: | Line 1,565: | ||
for key, count in sorted(bin.items()) ] |
for key, count in sorted(bin.items()) ] |
||
) |
) |
||
pp(dict(bin))</ |
pp(dict(bin))</syntaxhighlight> |
||
Sample output: |
Sample output: |
||
<pre>>>> distcheck(dice5, 1000000, 1) |
<pre>>>> distcheck(dice5, 1000000, 1) |
||
Line 1,581: | Line 1,581: | ||
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]]. |
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 |
[ 7 times |
||
Line 1,605: | Line 1,605: | ||
say "s is sketchy." |
say "s is sketchy." |
||
cr ] ] |
cr ] ] |
||
2drop temp release ] is distribution ( x n n --> )</ |
2drop temp release ] is distribution ( x n n --> )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,625: | Line 1,625: | ||
=={{header|R}}== |
=={{header|R}}== |
||
< |
<syntaxhighlight lang="r">distcheck <- function(fn, repetitions=1e4, delta=3) |
||
{ |
{ |
||
if(is.character(fn)) |
if(is.character(fn)) |
||
Line 1,644: | Line 1,644: | ||
data.frame(value=names(counts), counts=as.vector(counts), status=status) |
data.frame(value=names(counts), counts=as.vector(counts), status=status) |
||
} |
} |
||
distcheck(dice7.vec)</ |
distcheck(dice7.vec)</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Line 1,651: | Line 1,651: | ||
Returns a pair of a boolean stating uniformity and either the "uniform" distribution or a report of the first skew number found. |
Returns a pair of a boolean stating uniformity and either the "uniform" distribution or a report of the first skew number found. |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(define (pretty-fraction f) |
(define (pretty-fraction f) |
||
(if (integer? f) f |
(if (integer? f) f |
||
Line 1,687: | Line 1,687: | ||
(test-uniformity/naive straight-die 1000 5) |
(test-uniformity/naive straight-die 1000 5) |
||
; Test whether a biased die fails: |
; Test whether a biased die fails: |
||
(test-uniformity/naive crooked-die 1000 5)</ |
(test-uniformity/naive crooked-die 1000 5)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,697: | Line 1,697: | ||
(formerly Perl 6) |
(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. |
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. |
||
<lang |
<syntaxhighlight lang="raku" line>my $d7 = 1..7; |
||
sub roll7 { $d7.roll }; |
sub roll7 { $d7.roll }; |
||
Line 1,721: | Line 1,721: | ||
} |
} |
||
say ''; |
say ''; |
||
}</ |
}</syntaxhighlight> |
||
Sample output: |
Sample output: |
||
<pre> |
<pre> |
||
Line 1,780: | Line 1,780: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
< |
<syntaxhighlight lang="rexx">/*REXX program simulates a number of trials of a random digit and show it's skew %. */ |
||
parse arg func times delta seed . /*obtain arguments (options) from C.L. */ |
parse arg func times delta seed . /*obtain arguments (options) from C.L. */ |
||
if func=='' | func=="," then func= 'RANDOM' /*function not specified? Use default.*/ |
if func=='' | func=="," then func= 'RANDOM' /*function not specified? Use default.*/ |
||
Line 1,813: | Line 1,813: | ||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
commas: parse arg _; do jc=length(_)-3 to 1 by -3; _=insert(',', _, jc); end; return _ |
commas: parse arg _; do jc=length(_)-3 to 1 by -3; _=insert(',', _, jc); end; return _ |
||
sep: say pad '─────' center('', w, '─') '──────' "──────" '──────'; return</ |
sep: say pad '─────' center('', w, '─') '──────' "──────" '──────'; return</syntaxhighlight> |
||
{{out|output|text= when using the default inputs:}} |
{{out|output|text= when using the default inputs:}} |
||
<pre> |
<pre> |
||
Line 1,834: | Line 1,834: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
# Project : Verify distribution uniformity/Naive |
# Project : Verify distribution uniformity/Naive |
||
Line 1,865: | Line 1,865: | ||
func dice5 |
func dice5 |
||
return random(5) |
return random(5) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,876: | Line 1,876: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
{{trans|Tcl}} |
{{trans|Tcl}} |
||
< |
<syntaxhighlight lang="ruby">def distcheck(n, delta=1) |
||
unless block_given? |
unless block_given? |
||
raise ArgumentError, "pass a block to this method" |
raise ArgumentError, "pass a block to this method" |
||
Line 1,902: | Line 1,902: | ||
p e |
p e |
||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,919: | Line 1,919: | ||
=={{header|Run BASIC}}== |
=={{header|Run BASIC}}== |
||
< |
<syntaxhighlight lang="runbasic">s$ = "#########################" |
||
dim num(100) |
dim num(100) |
||
for i = 1 to 1000 |
for i = 1 to 1000 |
||
Line 1,928: | Line 1,928: | ||
for i = 1 to 10 |
for i = 1 to 10 |
||
print using("###",i);" "; using("#####",num(i));" ";left$(s$,num(i) / 5) |
print using("###",i);" "; using("#####",num(i));" ";left$(s$,num(i) / 5) |
||
next i</ |
next i</syntaxhighlight><pre> |
||
1 90 ################## |
1 90 ################## |
||
2 110 ###################### |
2 110 ###################### |
||
Line 1,942: | Line 1,942: | ||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
===Imperative, ugly, mutable data=== |
===Imperative, ugly, mutable data=== |
||
< |
<syntaxhighlight lang="scala">object DistrubCheck1 extends App { |
||
private def distCheck(f: () => Int, nRepeats: Int, delta: Double): Unit = { |
private def distCheck(f: () => Int, nRepeats: Int, delta: Double): Unit = { |
||
Line 1,965: | Line 1,965: | ||
distCheck(() => 1 + util.Random.nextInt(5), 1_000_000, 1) |
distCheck(() => 1 + util.Random.nextInt(5), 1_000_000, 1) |
||
}</ |
}</syntaxhighlight> |
||
===Functional Style=== |
===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)]. |
{{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)]. |
||
< |
<syntaxhighlight lang="scala">object DistrubCheck2 extends App { |
||
private def distCheck(f: () => Int, nRepeats: Int, delta: Double): Unit = { |
private def distCheck(f: () => Int, nRepeats: Int, delta: Double): Unit = { |
||
val counts: Map[Int, Int] = |
val counts: Map[Int, Int] = |
||
Line 1,983: | Line 1,983: | ||
distCheck(() => 1 + util.Random.nextInt(5), 1_000_000, 1) |
distCheck(() => 1 + util.Random.nextInt(5), 1_000_000, 1) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">proc distcheck {random times {delta 1}} { |
||
for {set i 0} {$i<$times} {incr i} {incr vals([uplevel 1 $random])} |
for {set i 0} {$i<$times} {incr i} {incr vals([uplevel 1 $random])} |
||
set target [expr {$times / [array size vals]}] |
set target [expr {$times / [array size vals]}] |
||
Line 1,996: | Line 1,996: | ||
foreach k [lsort -integer [array names vals]] {lappend result $k $vals($k)} |
foreach k [lsort -integer [array names vals]] {lappend result $k $vals($k)} |
||
return $result |
return $result |
||
}</ |
}</syntaxhighlight> |
||
Demonstration: |
Demonstration: |
||
< |
<syntaxhighlight lang="tcl"># First, a uniformly distributed random variable |
||
puts [distcheck {expr {int(10*rand())}} 100000] |
puts [distcheck {expr {int(10*rand())}} 100000] |
||
# Now, one that definitely isn't! |
# Now, one that definitely isn't! |
||
puts [distcheck {expr {rand()>0.95}} 100000]</ |
puts [distcheck {expr {rand()>0.95}} 100000]</syntaxhighlight> |
||
Which produces this output (error in red): |
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 |
0 10003 1 9851 2 10058 3 10193 4 10126 5 10002 6 9852 7 9964 8 9957 9 9994 |
||
Line 2,008: | Line 2,008: | ||
=={{header|VBScript}}== |
=={{header|VBScript}}== |
||
< |
<syntaxhighlight lang="vb">Option Explicit |
||
sub verifydistribution(calledfunction, samples, delta) |
sub verifydistribution(calledfunction, samples, delta) |
||
Line 2,031: | Line 2,031: | ||
& ", desired limit is " & FormatPercent(delta, 2) & "." |
& ", desired limit is " & FormatPercent(delta, 2) & "." |
||
if maxdiff > delta then wscript.echo "Skewed!" else wscript.echo "Smooth!" |
if maxdiff > delta then wscript.echo "Skewed!" else wscript.echo "Smooth!" |
||
end sub</ |
end sub</syntaxhighlight> |
||
Demonstration with included [[Seven-sided dice from five-sided dice#VBScript]] code: |
Demonstration with included [[Seven-sided dice from five-sided dice#VBScript]] code: |
||
< |
<syntaxhighlight lang="vb">verifydistribution "dice7", 1000, 0.03 |
||
verifydistribution "dice7", 100000, 0.03</ |
verifydistribution "dice7", 100000, 0.03</syntaxhighlight> |
||
Which produces this output: |
Which produces this output: |
||
Running "dice7" 1000 times... |
Running "dice7" 1000 times... |
||
Line 2,061: | Line 2,061: | ||
=={{header|Vlang}}== |
=={{header|Vlang}}== |
||
{{trans|go}} |
{{trans|go}} |
||
< |
<syntaxhighlight lang="vlang">import rand |
||
import rand.seed |
import rand.seed |
||
import math |
import math |
||
Line 2,112: | Line 2,112: | ||
max, flat_enough = dist_check(dice7, 7, calls, 500) |
max, flat_enough = dist_check(dice7, 7, calls, 500) |
||
println("Max delta: $max Flat enough: $flat_enough") |
println("Max delta: $max Flat enough: $flat_enough") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,123: | Line 2,123: | ||
{{libheader|Wren-fmt}} |
{{libheader|Wren-fmt}} |
||
{{libheader|Wren-sort}} |
{{libheader|Wren-sort}} |
||
< |
<syntaxhighlight lang="ecmascript">import "random" for Random |
||
import "/fmt" for Fmt |
import "/fmt" for Fmt |
||
import "/sort" for Sort |
import "/sort" for Sort |
||
Line 2,157: | Line 2,157: | ||
checkDist.call(dice5, 1e6, 0.5) |
checkDist.call(dice5, 1e6, 0.5) |
||
System.print() |
System.print() |
||
checkDist.call(dice5, 1e5, 0.5)</ |
checkDist.call(dice5, 1e5, 0.5)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,189: | Line 2,189: | ||
=={{header|zkl}}== |
=={{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. |
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. |
||
< |
<syntaxhighlight lang="zkl">fcn rtest(N){ |
||
dist:=L(0,0,0,0,0,0,0,0,0,0); |
dist:=L(0,0,0,0,0,0,0,0,0,0); |
||
do(N){n:=(0).random(10); dist[n]=dist[n]+1} |
do(N){n:=(0).random(10); dist[n]=dist[n]+1} |
||
Line 2,200: | Line 2,200: | ||
n:=10; |
n:=10; |
||
while(not rtest(n)) {n*=2}</ |
while(not rtest(n)) {n*=2}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Reported numbers is the percent that bucket has of all samples. |
Reported numbers is the percent that bucket has of all samples. |