Skip to content
Prev Previous commit
Next Next commit
system.Random.Sample snippet
  • Loading branch information
albert-du committed Oct 29, 2021
commit 5ae5a0f554c335d6f1a81d17138f59605a7c3130
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// <Snippet1>
open System

// This derived class converts the uniformly distributed random
// numbers generated by base.Sample() to another distribution.

type RandomProportional() =
inherit Random()

// The Sample method generates a distribution proportional to the value
// of the random numbers, in the range [0.0, 1.0].
override _.Sample() =
sqrt (base.Sample())

override this.Next() =
this.Sample() * float Int32.MaxValue
|> int

let [<Literal>] rows = 4
let [<Literal>] cols = 6
let [<Literal>] runCount = 1000000
let [<Literal>] distGroupCount = 10

let intGroupSize =
(float Int32.MaxValue + 1.0) / float distGroupCount

let randObj = RandomProportional()

printfn """
The derived RandomProportional class overrides the Sample method to
generate random numbers in the range [0.0, 1.0]. The distribution
of the numbers is proportional to their numeric values. For example,
numbers are generated in the vicinity of 0.75 with three times the
probability of those generated near 0.25."""

printfn "\nRandom doubles generated with the NextDouble() method:\n"

// Generate and display [rows * cols] random doubles.
for _ = 1 to rows do
for _ = 1 to cols do
printf $"{randObj.NextDouble(),12:F8}"
printfn ""

printfn "\nRandom integers generated with the Next() method:\n"
// Generate and display [rows * cols] random integers.
for _ = 1 to rows do
for _ = 1 to cols do
printf $"{randObj.Next(),12}"
printfn ""

printfn $"""
To demonstrate the proportional distribution,
{runCount:N0} random
integers and doubles are grouped into {distGroupCount} equal value ranges. This
is the count of values in each range:
"""

printfn $"""{"Integer Range",21}{"Count",10}{"Double Range",20}{"Count",10}"""
printfn $"""{"-------------",21}{"-----",10}{"------------",20}{"-----",10}"""

// Generate random integers and doubles, and then count them by group.
let intCounts =
Array.init runCount (fun _ ->
(randObj.Next() |> float) / float intGroupSize
|> int )
|> Array.countBy id
|> Array.map snd

let realCounts =
Array.init runCount (fun _ ->
randObj.NextDouble() * float intGroupSize
|> int )
|> Array.countBy id
|> Array.map snd

// Display the count of each group.
for i = 1 to distGroupCount - 1 do
Console.WriteLine(
"{0,10}-{1,10}{2,10:N0}{3,12:N5}-{4,7:N5}{5,10:N0}",
(int)((float)i * intGroupSize),
(int)((float)(i + 1) * intGroupSize - 1.0),
intCounts.[i],
((float)i) / (float)distGroupCount,
((float)(i + 1)) / (float)distGroupCount,
realCounts.[i])

(*
This example of Random.Sample() displays output similar to the following:

The derived RandomProportional class overrides the Sample method to
generate random numbers in the range [0.0, 1.0). The distribution
of the numbers is proportional to the number values. For example,
numbers are generated in the vicinity of 0.75 with three times the
probability of those generated near 0.25.

Random doubles generated with the NextDouble() method:

0.59455719 0.17589882 0.83134398 0.35795862 0.91467727 0.54022658
0.93716947 0.54817519 0.94685080 0.93705478 0.18582318 0.71272428
0.77708682 0.95386216 0.70412393 0.86099417 0.08275804 0.79108316
0.71019941 0.84205103 0.41685082 0.58186880 0.89492302 0.73067715

Random integers generated with the Next() method:

1570755704 1279192549 1747627711 1705700211 1372759203 1849655615
2046235980 1210843924 1554274149 1307936697 1480207570 1057595022
337854215 844109928 2028310798 1386669369 2073517658 1291729809
1537248240 1454198019 1934863511 1640004334 2032620207 534654791

To demonstrate the proportional distribution, 1,000,000 random
integers and doubles are grouped into 10 equal value ranges. This
is the count of values in each range:

Integer Range Count Double Range Count
------------- ----- ------------ -----
0- 214748363 10,079 0.00000-0.10000 10,148
214748364- 429496728 29,835 0.10000-0.20000 29,849
429496729- 644245093 49,753 0.20000-0.30000 49,948
644245094- 858993458 70,325 0.30000-0.40000 69,656
858993459-1073741823 89,906 0.40000-0.50000 90,337
1073741824-1288490187 109,868 0.50000-0.60000 110,225
1288490188-1503238552 130,388 0.60000-0.70000 129,986
1503238553-1717986917 149,231 0.70000-0.80000 150,428
1717986918-1932735282 170,234 0.80000-0.90000 169,610
1932735283-2147483647 190,381 0.90000-1.00000 189,813
*)
// </Snippet1>

1 change: 1 addition & 0 deletions xml/System/Random.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,7 @@ Each element of the span of bytes is set to a random number greater than or equa

:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.Random.Sample/cpp/sampleex.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/system.Random.Sample/CS/sample.cs" interactive="try-dotnet" id="Snippet1":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/system.Random.Sample/FS/sample.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.Random.Sample/VB/sample.vb" id="Snippet1":::

]]></format>
Expand Down