Shuffle bias comparison

Compare naive shuffling vs Fisher–Yates under identical settings.

Runs locally in your browser. Inputs and results are not uploaded. Copy URL shares settings only.

Other languages: ja | en | es

How to use (3 steps)

  1. Choose list mode (size or custom) and set trials.
  2. Click Compare to run both shuffles with the same settings.
  3. Review heatmaps & stats, then copy a settings-only URL or download a report.

See bias in shuffling

Shuffle bias comparison tool

Naive swapping uses a full-range random index at every step. Fisher–Yates uses a shrinking range, making permutations uniform (with uniform randomInt).

This is a common anti-pattern in JavaScript. Results depend on your engine and are typically biased.

Summary

Tip: The chi-square df here is a heuristic (constraints exist). Use it for intuition, not as a formal proof.

Charts

Legend: naive=red, FY=green, sort=purple (if enabled).

The curve is a chi-square density with df = n² - 1 (heuristic). Vertical lines show your observed χ².

This chart aggregates cells by |i - j| (distance from the diagonal). Values above 1 indicate “too close to the original position”.

Results

Each side shows a position matrix (item i → position j) aggregated over trials.

Naive shuffle

Fisher–Yates

Frequently asked questions

Is Fisher–Yates always unbiased?
It is unbiased if your randomInt is uniform. Avoid modulo bias when converting random bytes to an integer range.
Why not use sort(() => random - 0.5)?
It is biased and engine-dependent. You can optionally include it on this page to see what happens in your browser.
Does passing this mean cryptographic security?
No. This tool illustrates algorithmic bias in shuffling. Security depends on your RNG and threat model.
What trials should I use?
Start with 100k. For n ≤ 8, enabling permutation tracking helps show bias more directly.

Related tools

Related calculators