diff options
-rw-r--r-- | src/gleam/float.gleam | 13 | ||||
-rw-r--r-- | src/gleam/int.gleam | 28 | ||||
-rw-r--r-- | src/gleam_stdlib.mjs | 13 |
3 files changed, 30 insertions, 24 deletions
diff --git a/src/gleam/float.gleam b/src/gleam/float.gleam index 1b8220b..d41bc21 100644 --- a/src/gleam/float.gleam +++ b/src/gleam/float.gleam @@ -338,22 +338,19 @@ if erlang { } if javascript { - /// With round-to-nearest-even behavior, the ranges claimed for the functions below - /// (excluding the one for Math.random() itself) aren't exact. - /// If extremely large bounds are chosen (2^53 or higher), - /// it's possible in extremely rare cases to calculate the usually-excluded upper bound. - /// Note that as numbers in JavaScript are IEEE 754 floating point numbers - /// See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random> - /// external fn do_random_uniform() -> Float = "../gleam_stdlib.mjs" "random_uniform" } pub fn random_between(min: Float, max: Float) -> Float { // ```javascript - // return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is/should-be exclusive + // return Math.random() * (max - min) + min; // The minimum is inclusive and the maximum is exclusive // ``` // See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_number_between_two_values> // random_uniform() *. { max -. min } +. min } + +pub fn random_below(max: Float) -> Float { + random_uniform() *. max +} diff --git a/src/gleam/int.gleam b/src/gleam/int.gleam index c255dd0..06ad12c 100644 --- a/src/gleam/int.gleam +++ b/src/gleam/int.gleam @@ -1,5 +1,4 @@ import gleam/order.{Order} -// import gleam/float.{floor, parse, random} import gleam/float /// Returns the absolute value of the input. @@ -383,26 +382,25 @@ fn do_undigits( } } -pub fn random_below(max: Int) -> Int { - // ```javascript - // return Math.floor(rand * max); - // ``` - // See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random> - float.random_uniform() *. to_float(max) - |> float.floor() - |> float.round() - // TODO: Does `float.round() `affect random distribution uniformity? -} - pub fn random_between(min: Int, max: Int) -> Int { // ```javascript // min = Math.ceil(min); // max = Math.floor(max); - // return Math.floor(Math.random() * (max - min + 1) + min); //The maximum is inclusive and the minimum is inclusive + // return Math.floor(Math.random() * (max - min) + min); // The minimum is inclusive and the maximum is exclusive // ``` // See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values> - float.random_between(to_float(min), to_float(max)) + let min = + to_float(min) + |> float.ceiling() + let max = + to_float(max) + |> float.floor() + + float.random_between(min, max) |> float.floor() |> float.round() - // TODO: Does float.round() affect random distribution uniformity? +} + +pub fn random_below(max: Int) -> Int { + random_between(0, max) } diff --git a/src/gleam_stdlib.mjs b/src/gleam_stdlib.mjs index 59077e9..6604bff 100644 --- a/src/gleam_stdlib.mjs +++ b/src/gleam_stdlib.mjs @@ -247,7 +247,18 @@ export function power(base, exponent) { } export function random_uniform() { - return Math.random(); + let random_uniform_result = Math.random(); + // With round-to-nearest-even behavior, the ranges claimed for the functions below + // (excluding the one for Math.random() itself) aren't exact. + // If extremely large bounds are chosen (2^53 or higher), + // it's possible in extremely rare cases to calculate the usually-excluded upper bound. + // Note that as numbers in JavaScript are IEEE 754 floating point numbers + // See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random> + // Because of this, we just loop 'until' we get a valid result where 0.0 <= x < 1.0: + if (random_uniform_result === 1.0) { + return random_uniform(); + } + return random_uniform_result; } export function bit_string_slice(bits, position, length) { |