116 lines
3.5 KiB
Ada
116 lines
3.5 KiB
Ada
with Ada.Text_Io;
|
|
with Ada.Numerics.Float_Random;
|
|
with Ada.Strings.Fixed;
|
|
|
|
procedure Modified_Distribution is
|
|
|
|
Observations : constant := 20_000;
|
|
Buckets : constant := 25;
|
|
Divider : constant := 12;
|
|
Char : constant Character := '*';
|
|
|
|
generic
|
|
with function Modifier (X : Float) return Float;
|
|
package Generic_Random is
|
|
function Random return Float;
|
|
end Generic_Random;
|
|
|
|
package body Generic_Random is
|
|
package Float_Random renames Ada.Numerics.Float_Random;
|
|
Generator : Float_Random.Generator;
|
|
|
|
function Random return Float is
|
|
Random_1 : Float;
|
|
Random_2 : Float;
|
|
begin
|
|
loop
|
|
Random_1 := Float_Random.Random (Generator);
|
|
Random_2 := Float_Random.Random (Generator);
|
|
if Random_2 < Modifier (Random_1) then
|
|
return Random_1;
|
|
end if;
|
|
end loop;
|
|
end Random;
|
|
|
|
begin
|
|
Float_Random.Reset (Generator);
|
|
end Generic_Random;
|
|
|
|
generic
|
|
Buckets : in Positive;
|
|
package Histograms is
|
|
type Bucket_Index is new Positive range 1 .. Buckets;
|
|
Bucket_Width : constant Float := 1.0 / Float (Buckets);
|
|
procedure Clean;
|
|
procedure Increment_Bucket (Observation : Float);
|
|
function Observations_In (Bucket : Bucket_Index) return Natural;
|
|
function To_Bucket (X : Float) return Bucket_Index;
|
|
function Range_Image (Bucket : Bucket_Index) return String;
|
|
end Histograms;
|
|
|
|
package body Histograms is
|
|
Hist : array (Bucket_Index) of Natural := (others => 0);
|
|
|
|
procedure Clean is
|
|
begin
|
|
Hist := (others => 0);
|
|
end Clean;
|
|
|
|
procedure Increment_Bucket (Observation : Float) is
|
|
Bin : constant Bucket_Index := To_Bucket (Observation);
|
|
begin
|
|
Hist (Bin) := Hist (Bin) + 1;
|
|
end Increment_Bucket;
|
|
|
|
function Observations_In (Bucket : Bucket_Index) return Natural
|
|
is (Hist (Bucket));
|
|
|
|
function To_Bucket (X : Float) return Bucket_Index
|
|
is (1 + Bucket_Index'Base (Float'Floor (X / Bucket_Width)));
|
|
|
|
function Range_Image (Bucket : Bucket_Index) return String is
|
|
package Float_Io is new Ada.Text_Io.Float_Io (Float);
|
|
Image : String := "F.FF..L.LL";
|
|
First : constant Float := Float (Bucket - 1) / Float (Buckets);
|
|
Last : constant Float := Float (Bucket - 1 + 1) / Float (Buckets);
|
|
begin
|
|
Float_Io.Put (Image (1 .. 4), First, Exp => 0, Aft => 2);
|
|
Float_Io.Put (Image (7 .. 10), Last, Exp => 0, Aft => 2);
|
|
return Image;
|
|
end Range_Image;
|
|
|
|
begin
|
|
Clean;
|
|
end Histograms;
|
|
|
|
function Modifier (X : Float) return Float
|
|
is (if X in Float'First .. 0.5
|
|
then 2.0 * (0.5 - X)
|
|
else 2.0 * (X - 0.5));
|
|
|
|
package Modified_Random is
|
|
new Generic_Random (Modifier => Modifier);
|
|
|
|
package Histogram_20 is
|
|
new Histograms (Buckets => Buckets);
|
|
|
|
function Column (Height : Natural; Char : Character) return String
|
|
renames Ada.Strings.Fixed."*";
|
|
|
|
use Ada.Text_Io;
|
|
begin
|
|
for N in 1 .. Observations loop
|
|
Histogram_20.Increment_Bucket (Modified_Random.Random);
|
|
end loop;
|
|
|
|
Put ("Range Observations: "); Put (Observations'Image);
|
|
Put (" Buckets: "); Put (Buckets'Image);
|
|
New_Line;
|
|
for I in Histogram_20.Bucket_Index'Range loop
|
|
Put (Histogram_20.Range_Image (I));
|
|
Put (" ");
|
|
Put (Column (Histogram_20.Observations_In (I) / Divider, Char));
|
|
New_Line;
|
|
end loop;
|
|
end Modified_Distribution;
|