Make max of Random methods inclusive rather than exclusive (#8768)

* Make max inclusive rather than exclusive

* Update names to min max. Remove end_inclusive

* Indicies should remain exclusive

* Make the tests pass
This commit is contained in:
AdRiley 2024-01-24 16:58:33 +00:00 committed by GitHub
parent 6eb00a7c5f
commit 23d6fcdd9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 32 additions and 40 deletions

View File

@ -64,18 +64,18 @@ type Random
## GROUP Random
Return a random `Integer` between `min` (inclusive) and `max`
(exclusive).
(inclusive).
Arguments:
- min: The minimum value of the range to pick from (inclusive).
- max: The maximum value of the range to pick from (exclusive).
- max: The maximum value of the range to pick from (inclusive).
> Example
Generate an integer between 1 and 10.
import Standard.Base.Random.Random
i = Random.integer 1 11
i = Random.integer 1 10
integer : Integer -> Integer -> Integer ! Illegal_Argument
integer (min:Integer) (max:Integer) = Random_Generator.global_random_generator.integer min max
@ -146,8 +146,8 @@ type Random
Return a `Date` within the specified `Date_Range`.
Arguments:
- start_date: The lower bound of the range to pick from (inclusive).
- end_date: The upper bound of the range to pick from (exclusive).
- min: The lower bound of the range to pick from (inclusive).
- max: The upper bound of the range to pick from (inclusive).
> Example
Generate a random date.
@ -156,22 +156,19 @@ type Random
d = Random.date (Date.new 2023 03 01) (Date.new 2023 10 15)
date : Date -> Date -> Boolean -> Date
date start_date:Date end_date:Date end_exclusive=True = Random_Generator.global_random_generator.date start_date end_date end_exclusive
date min:Date max:Date = Random_Generator.global_random_generator.date min max
## GROUP Random
Return a `Time_Of_Day` between `start_time` and `end_time` (inclusive).
Arguments:
- start_time: The lower bound of the range to pick from (inclusive).
- end_time: The upper bound of the range to pick from (inclusive).
- min: The lower bound of the range to pick from (inclusive).
- max: The upper bound of the range to pick from (inclusive).
The generated time is at a granularity of 1 second. Random values are
generated for hours, minutes and seconds. The `nanoseconds` field is
always 0.
Note: the time range end is inclusive because it is impossible to specify
an end time after the last second of the day.
> Example
Generate a random time.
@ -181,8 +178,8 @@ type Random
end = Time_Of_Day.new 9 40 2
t = Random.time start end
time : Time_Of_Day -> Time_Of_Day -> Time_Of_Day
time (start_time:Time_Of_Day=(Time_Of_Day.new 0 0 0)) (end_time:Time_Of_Day=(Time_Of_Day.new 23 59 59)) =
Random_Generator.global_random_generator.time start_time end_time
time (min:Time_Of_Day=(Time_Of_Day.new 0 0 0)) (max:Time_Of_Day=(Time_Of_Day.new 23 59 59)) =
Random_Generator.global_random_generator.time min max
## GROUP Random
Return a new UUID.
@ -273,7 +270,7 @@ type Random_Generator
## PRIVATE
integer : Integer -> Integer -> Integer ! Illegal_Argument
integer self (min:Integer) (max:Integer) =
range = max - min
range = max - min + 1
if range >= Java_Integer.MAX_VALUE then Error.throw (Illegal_Argument.Error "Currently only integer ranges of up to 2^31-1 are supported.") else
min + (self.java_random.nextInt range)
@ -301,16 +298,16 @@ type Random_Generator
## PRIVATE
date : Date -> Date -> Boolean -> Date
date self start_date:Date end_date:Date end_exclusive=True =
date_range = start_date.up_to end_date include_end=end_exclusive.not
date_range.at (self.integer 0 date_range.length)
date self start_date:Date end_date:Date =
date_range = start_date.up_to end_date include_end=True
date_range.at (self.integer 0 (date_range.length - 1))
## PRIVATE
time : Time_Of_Day -> Time_Of_Day -> Time_Of_Day
time self (start_time:Time_Of_Day=(Time_Of_Day.new 0 0 0)) (end_time:Time_Of_Day=(Time_Of_Day.new 23 59 59)) =
## The time range end is inclusive because it is impossible to specify
an end time after the last second of the day.
seconds = self.integer 0 (end_time.to_seconds - start_time.to_seconds + 1)
seconds = self.integer 0 (end_time.to_seconds - start_time.to_seconds)
start_time.date_add seconds Time_Period.Second
## PRIVATE
@ -323,7 +320,7 @@ type Random_Generator
case with_replacement of
True ->
len = v.length
0.up_to count . map _-> v.at (self.integer 0 len)
0.up_to count . map _-> v.at (self.integer 0 (len - 1))
False ->
if count > v.length then Error.throw (Illegal_Argument.Error "`count` cannot be greater than the size of the collection when `with_replacement` is false") else
new_array = Random_Utils.sample v count self.java_random

View File

@ -8,12 +8,12 @@ import Standard.Test.Extensions
spec = Test.group "Random" <|
Test.specify "should allow generating random integers" <|
Random.set_seed 12345
Random.integer 0 100 . should_equal 51
Random.integer 0 10000 . should_equal 9080
Random.integer 0 99 . should_equal 51
Random.integer 0 9999 . should_equal 9080
random_range = 0.up_to 1000 . map (_-> Random.integer 0 100) . compute_bulk [Statistic.Minimum, Statistic.Maximum]
random_range = 0.up_to 1000 . map (_-> Random.integer 0 99) . compute_bulk [Statistic.Minimum, Statistic.Maximum]
(random_range.at 0 >= 0) . should_equal True
(random_range.at 1 <= 100) . should_equal True
(random_range.at 1 <= 99) . should_equal True
Test.specify "should allow generating random floats" <|
Random.set_seed 12345
@ -71,17 +71,12 @@ spec = Test.group "Random" <|
Test.specify "should allow generating random dates" <|
Random.set_seed 4000
Random.date (Date.new 2023 03 01) (Date.new 2023 10 15) . should_equal (Date.new 2023 6 9)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 15) . should_equal (Date.new 2023 7 16)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 15) . should_equal (Date.new 2023 10 12)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 14) . should_equal (Date.new 2023 6 9)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 14) . should_equal (Date.new 2023 7 16)
Random.date (Date.new 2023 03 01) (Date.new 2023 10 14) . should_equal (Date.new 2023 10 12)
all_from_small_range = [Date.new 2023 03 01, Date.new 2023 03 02, Date.new 2023 03 03]
dates = 0.up_to 100 . map (_-> Random.date (Date.new 2023 03 01) (Date.new 2023 03 04))
dates.should_contain_the_same_elements_as all_from_small_range
Test.specify "should allow generating random dates, with end_exclusive=False" <|
all_from_small_range = [Date.new 2023 03 01, Date.new 2023 03 02, Date.new 2023 03 03, Date.new 2023 03 04]
dates = 0.up_to 100 . map (_-> Random.date (Date.new 2023 03 01) (Date.new 2023 03 04) end_exclusive=False)
dates = 0.up_to 100 . map (_-> Random.date (Date.new 2023 03 01) (Date.new 2023 03 03))
dates.should_contain_the_same_elements_as all_from_small_range
Test.specify "should allow generating random times" <|
@ -148,13 +143,13 @@ spec = Test.group "Random" <|
permutations_2 . should_contain_the_same_elements_as all_permutations
Test.specify "should not allow using a too-large integer range" <|
high = 9223372036854775807000
high = 9223372036854775806999
Random.integer 0 high . should_fail_with Illegal_Argument
Test.specify "Can call an instance directly" <|
Random.new_generator . should_be_a Random_Generator
Random.new_generator 12345 . should_be_a Random_Generator
Random.new_generator 12345 . integer 0 100 . should_equal 51
Random.new_generator 12345 . integer 0 99 . should_equal 51
Random.new_generator 12345 . float . should_equal 0.3618031071604718 epsilon=0.00000001
Random.new_generator 12345 . gaussian . should_equal -0.187808989658912 epsilon=0.00000001

View File

@ -15,7 +15,7 @@ type Data
create n =
create_ints =
Vector.new n _->
Random.integer 0 (n.div 100)
Random.integer 0 ((n.div 100) - 1)
Data.Value create_ints
type Scenario

View File

@ -11,8 +11,8 @@ options = Bench.options . set_warmup (Bench.phase_conf 2 2) . set_measure (Bench
create_table : Integer -> Table
create_table num_rows =
rng = Random.new_generator 42
x = Vector.new num_rows _-> rng.integer min=0 max=50
y = Vector.new num_rows _-> rng.integer min=0 max=10000
x = Vector.new num_rows _-> rng.integer min=0 max=49
y = Vector.new num_rows _-> rng.integer min=0 max=9999
t = Table.new [["X", x], ["Y", y]]
assert condition =

View File

@ -26,11 +26,11 @@ Comparable.from (_:My_Pair) = My_Pair_Comparator
create_table : Integer -> Table
create_table num_rows =
rng = Random.new_generator 42
x = Vector.new num_rows _-> rng.integer min=0 max=100
x = Vector.new num_rows _-> rng.integer min=0 max=99
y = Vector.new num_rows _-> rng.integer min=0 max=20 . to_text
z = Vector.new num_rows _->
a = Random.integer min=0 max=100
b = Random.integer min=0 max=100
a = Random.integer min=0 max=99
b = Random.integer min=0 max=99
My_Pair.Value a b
t = Table.new [["X", x], ["Y", y], ["Z", z]]