Skip to content

Commit

Permalink
Fix randomBetween overflow and rounding issues
Browse files Browse the repository at this point in the history
  • Loading branch information
lionel-rowe committed Sep 4, 2024
1 parent f226f4c commit 9052d98
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
4 changes: 3 additions & 1 deletion random/between.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,7 @@ export function randomBetween(
throw new RangeError("max must be greater than or equal to min");
}

return (options?.prng ?? Math.random)() * (max - min) + min;
const x = (options?.prng ?? Math.random)();
const y = min * (1 - x) + max * x;
return y >= min && y < max ? y : min;
}
20 changes: 20 additions & 0 deletions random/between_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
import { randomBetween } from "./between.ts";
import { randomSeeded } from "./seeded.ts";
import {
assert,
assertAlmostEquals,
assertEquals,
assertGreaterOrEqual,
assertLessOrEqual,
assertNotEquals,
assertThrows,
} from "@std/assert";

Expand Down Expand Up @@ -86,3 +88,21 @@ Deno.test("randomBetween() allows min and max to be the same, in which case it r
const results = Array.from({ length: 3 }, () => randomBetween(9.99, 9.99));
assertEquals(results, [9.99, 9.99, 9.99]);
});

Deno.test("randomBetween() never returns max, even if the prng returns its max value", () => {
const prng = () => 0.9999999999999999;
const result = randomBetween(1, 2, { prng });
assertNotEquals(result, 2);
});

Deno.test("randomBetween() doesn't overflow even for min = -Number.MAX_VALUE; max = Number.MAX_VALUE", () => {
for (const val of [0, 0.5, 0.9999999999999999]) {
const result = randomBetween(
-Number.MAX_VALUE,
Number.MAX_VALUE,
{ prng: () => val! },
);
console.log(result)
assert(Number.isFinite(result));
}
});

0 comments on commit 9052d98

Please sign in to comment.