Files
entscheidomat/posts/04-coin-toss-physics-diaconis-bias-simulation.md
2026-08-05 19:33:11 +02:00

8.5 KiB
Raw Blame History

title, description, tags, canonical_url, target_keywords
title description tags canonical_url target_keywords
Simulating Diaconis' 50.8% Coin Flip Bias in Python & JavaScript (Monte Carlo Analysis) Why real physical coin flips are not 50/50, an analysis of the Diaconis-Holmes-Montgomery model, and how to write a Monte Carlo simulation in TypeScript & Python.
python
javascript
datascience
math
https://entscheidomat.com/ratgeber/kopf-oder-zahl-muenzwurf-online
münze werfen online
kopf oder zahl
digitaler münzwurf
münzwurf online
coin flip simulation

Simulating Diaconis' 50.8% Coin Flip Bias in Python & JavaScript (Monte Carlo Analysis)

For centuries, flipping a coin has served as the universal gold standard of fairness. From starting American football games to resolving judicial ties, society assumes that tossing a coin produces a pure 50/50 (0.50 vs 0.50) probability distribution.

However, in 2007, a landmark paper by Stanford mathematicians Persi Diaconis, Susan Holmes, and Richard Montgomery titled "Dynamical Bias in Coin Tossing" mathematically proved that physical coin flips are dynamically biased toward the side that faced up prior to the toss.

In 2023, an empirical study by František Bartoš et al. confirmed this theory across 350,757 physical coin flips with 46 different currencies: coins land on the same side they started on 50.8\% of the time.

In this article, we will examine the physics of coin toss precession, model the 50.8\% dynamical bias using Monte Carlo simulations in Python and TypeScript, and discuss why a digital Münze werfen online tool provides a strictly fairer outcome than a physical coin.


1. The Physics of the Diaconis-Holmes-Montgomery Model

Why is a flipped physical coin biased?

When a human flips a coin using their thumb, two distinct rotational motions occur simultaneously:

  1. Pitch Rotation: The coin flips over and over around its principal axis.
  2. Precession (Wobble): The angular momentum vector deviates slightly from the principal axis, causing the coin to wobble like a spinning top.
       Normal Axis
           │
           ├─── Precession Angle (α)
          / \
        ┌─┴─┐
        │ 🪙 │  <-- Rotating Coin
        └───┘

Because of precession, the coin spends slightly more time in the air with its initial starting face pointing upwards than pointing downwards.

Diaconis derived the probability p of a coin landing on its initial face as a function of the precession angle \alpha:

p = \frac{1}{2} + \frac{1}{\pi} \arcsin\left( \tan \alpha \right)

When integrated over normal human flipping dynamics, the theoretical expected probability of landing on the same starting side comes out to approximately $50.8%$.


2. Empirical Proof: The 350,757 Coin Toss Study

In 2023, researcher František Bartoš recruited 48 participants to perform 350,757 recorded coin flips across 46 different coins (USD, EUR, GBP, CAD, etc.).

Metric Empirical Observed Value
Total Recorded Flips 350,757
Same-Side Outcome Probability 50.808% (\pm 0.04\%)
Opposite-Side Outcome Probability 49.192%
Statistical Significance p < 0.0001 ($Z$-score > 9.5)

The "Catching vs. Landing" Factor

  • Caught in Hand: If the coin is caught mid-air and flipped onto the back of the hand, the 50.8\% same-side bias holds true.
  • Spun on Table: If a coin is spun like a top on a flat surface, Prägemünzen (coins with heavier relief on one side) can exhibit a huge bias up to 80/20 due to uneven mass distribution along the edge!

3. Writing a Monte Carlo Simulation in Python

Let's build a Monte Carlo simulation in Python using numpy and scipy to compare a physical coin flip (with 50.8\% same-side bias) against a cryptographically uniform digital coin toss.

import numpy as np
from scipy.stats import chisquare

def simulate_coin_tosses(n_flips: int = 100000, initial_face: str = "HEADS", physical_bias: float = 0.508):
    """
    Simulates N coin flips for both a physical coin (Diaconis bias) and a digital PRNG coin.
    """
    print(f"--- MONTE CARLO SIMULATION ({n_flips:,} Flips) ---")
    
    # 1. PHYSICAL COIN SIMULATION
    # True = Same face as start, False = Opposite face
    physical_draws = np.random.binomial(n=1, p=physical_bias, size=n_flips)
    physical_same = np.sum(physical_draws)
    physical_opp = n_flips - physical_same
    
    print(f"[Physical Coin] Same Side ({initial_face}): {physical_same:,} ({(physical_same/n_flips)*100:.2f}%)")
    print(f"[Physical Coin] Opposite Side: {physical_opp:,} ({(physical_opp/n_flips)*100:.2f}%)")
    
    # Chi-square test against ideal 50/50
    chi_phys, p_phys = chisquare([physical_same, physical_opp], [n_flips/2, n_flips/2])
    print(f"  └─ Chi-Square: {chi_phys:.4f}, p-value: {p_phys:.4e}")
    if p_phys < 0.05:
        print("  └─ ❌ REJECT NULL HYPOTHESIS: Physical coin is statistically BIASED!")

    print("\n" + "="*50 + "\n")

    # 2. DIGITAL COIN SIMULATION (Crypto PRNG)
    digital_draws = np.random.binomial(n=1, p=0.500, size=n_flips)
    digital_heads = np.sum(digital_draws)
    digital_tails = n_flips - digital_heads
    
    print(f"[Digital Coin] HEADS: {digital_heads:,} ({(digital_heads/n_flips)*100:.2f}%)")
    print(f"[Digital Coin] TAILS: {digital_tails:,} ({(digital_tails/n_flips)*100:.2f}%)")
    
    chi_dig, p_dig = chisquare([digital_heads, digital_tails], [n_flips/2, n_flips/2])
    print(f"  └─ Chi-Square: {chi_dig:.4f}, p-value: {p_dig:.4e}")
    if p_dig >= 0.05:
        print("  └─ ✅ ACCEPT NULL HYPOTHESIS: Digital coin is 100% UNBIASED!")

simulate_coin_tosses(100000)

4. TypeScript Implementation of a Digital Coin Toss

To eliminate physical precession bias, a digital coin toss must use crypto.getRandomValues() to pick between 0 (Heads) and 1 (Tails) with exact 50.000\% probability.

export type CoinSide = "HEADS" | "TAILS";

export interface CoinFlipResult {
  outcome: CoinSide;
  timestamp: number;
  entropyHex: string;
}

/**
 * Executes a 100% unbiased digital coin toss using Web Crypto API.
 */
export function flipDigitalCoin(): CoinFlipResult {
  const buffer = new Uint8Array(1);
  
  // Get 8 bits of cryptographic entropy
  let randomByte: number;
  do {
    crypto.getRandomValues(buffer);
    randomByte = buffer[0];
  } while (randomByte >= 254); // Reject upper remainder to eliminate modulo bias (254 % 2 == 0)

  const outcome: CoinSide = (randomByte % 2 === 0) ? "HEADS" : "TAILS";

  return {
    outcome,
    timestamp: Date.now(),
    entropyHex: randomByte.toString(16).padStart(2, '0')
  };
}

5. Physical vs. Digital Coin Comparison

Parameter Physical Coin Toss Digital Coin Toss (Münze Werfen)
Probability Split 50.8% / 49.2% (Same side bias) 50.0% / 50.0% (Pure uniform)
Precession Wobble Bias Present (\arcsin(\tan \alpha)) None
Edge Spin Weight Bias High (up to 80/20 on flat surfaces) None
Human Manipulation High (controlled thumb strength) Impossible
Remote Acceptance Low (requires physical presence) High (shareable result link)

Conclusion & Practical Takeaway

If you are using a physical coin to settle a decision:

  • Always cover the coin when calling "Kopf oder Zahl" before inspecting the initial face.
  • Alternatively, flip the coin and let it drop onto carpet rather than catching it.

For zero physical bias and instant 50/50 fairness, use a digital coin tool like the live Münze werfen online on Entscheidomat.


FAQ (Schema Structured Data)

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Is a physical coin toss truly 50/50?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No. Stanford research by Diaconis and a 350,757 empirical coin flip study proved physical coins land on their starting side 50.8% of the time due to rotational precession wobble."
      }
    },
    {
      "@type": "Question",
      "name": "Why is a digital coin flip fairer than a physical coin?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Digital coin flips use cryptographic pseudo-random number generators (Web Crypto API) that have no physical precession, mass imbalance, or human throw technique bias, guaranteeing a true 50.0% split."
      }
    }
  ]
}