Skip to content

Commit

Permalink
Ensure random numbers are correctly distributed (#3734)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikearnaldi authored Oct 6, 2024
1 parent 5266b6c commit 88e85db
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-falcons-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

Ensure random numbers are correctly distributed
16 changes: 1 addition & 15 deletions packages/effect/src/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -614,21 +614,7 @@ export class PCGRandom {
* @since 2.0.0
*/
integer(max: number) {
if (!max) {
return this._next()
}
max = max >>> 0
if ((max & (max - 1)) === 0) {
return this._next() & (max - 1) // fast path for power of 2
}

let num = 0
const skew = (-max >>> 0) % max >>> 0
for (num = this._next(); num < skew; num = this._next()) {
// this loop will rarely execute more than twice,
// and is intentionally empty
}
return num % max
return Math.round(this.number() * Number.MAX_SAFE_INTEGER) % max
}

/**
Expand Down
9 changes: 9 additions & 0 deletions packages/effect/test/Random.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import { expect, it } from "effect/test/utils/extend"
import { assert, describe } from "vitest"

describe("Random", () => {
it.effect("integer is correctly distributed", () =>
Effect.gen(function*() {
const tenYearsMillis = 10 * 365 * 24 * 60 * 60 * 1000
let lastRandom = 0
while (lastRandom < tenYearsMillis / 2) {
lastRandom = yield* Random.nextIntBetween(0, tenYearsMillis)
}
assert.isTrue(lastRandom >= tenYearsMillis / 2)
}))
it.effect("shuffle", () =>
Effect.gen(function*() {
const start = Array.range(0, 100)
Expand Down

0 comments on commit 88e85db

Please sign in to comment.