201 lines
8.5 KiB
Markdown
201 lines
8.5 KiB
Markdown
---
|
||
title: "Simulating Diaconis' 50.8% Coin Flip Bias in Python & JavaScript (Monte Carlo Analysis)"
|
||
description: "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."
|
||
tags: ["python", "javascript", "datascience", "math"]
|
||
canonical_url: "https://entscheidomat.com/ratgeber/kopf-oder-zahl-muenzwurf-online"
|
||
target_keywords: ["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](https://entscheidomat.com/muenze-werfen) 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.
|
||
|
||
```text
|
||
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.
|
||
|
||
```python
|
||
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.
|
||
|
||
```typescript
|
||
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](https://entscheidomat.com/muenze-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](https://entscheidomat.com/muenze-werfen).
|
||
|
||
---
|
||
|
||
## FAQ (Schema Structured Data)
|
||
|
||
```json
|
||
{
|
||
"@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."
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|