// Exact integer educational probability calculation; no network/storage/analytics. const SCALE=1000000n; export function parseProbabilities(raw){ const s=String(raw).trim();if(!s)throw Error('0.5처럼 확률을 입력하세요.');const tokens=s.split(/[\s,]+/);if(tokens.length>20)throw Error('최대 20개까지 계산합니다.'); return tokens.map(t=>{if(!/^(?:0(?:\.\d{1,6})?|1(?:\.0{1,6})?)$/.test(t))throw Error('각 확률은 0~1, 소수 여섯 자리까지 0.5처럼 적으세요.');const[a,b='']=t.split('.');return BigInt(a)*SCALE+BigInt(b.padEnd(6,'0'));}); } export function distribution(raw){const probs=parseProbabilities(raw);let numerators=[1n],denominator=1n;for(const p of probs){const next=Array(numerators.length+1).fill(0n);numerators.forEach((v,k)=>{next[k]+=v*(SCALE-p);next[k+1]+=v*p;});numerators=next;denominator*=SCALE;}return {shots:probs.length,expectedUnits:probs.reduce((a,b)=>a+b,0n),numerators,denominator,zero:numerators[0],atLeastOne:denominator-numerators[0]};} export function formatted(n,d,places=4){const scale=10n**BigInt(places),v=(n*scale*2n+d)/(2n*d);return `${v/scale}.${(v%scale).toString().padStart(places,'0')}`;} if(typeof document!=='undefined'){ const input=document.getElementById('xg-input'),out=document.getElementById('xg-output'),body=document.getElementById('xg-rows'); function draw(){try{const r=distribution(input.value);out.textContent=`가상 슈팅 ${r.shots}개 · xG 합계 ${formatted(r.expectedUnits,SCALE,6)}\n독립 가정의 무득점 확률 ${formatted(r.zero*100n,r.denominator,6)}%\n적어도 한 골 확률 ${formatted(r.atLeastOne*100n,r.denominator,6)}%\n실제 경기 예측이나 관측값이 아닙니다.`;body.replaceChildren();r.numerators.forEach((v,k)=>{const tr=document.createElement('tr');for(const x of [k,`${formatted(v*100n,r.denominator,6)}%`]){const td=document.createElement('td');td.textContent=x;tr.append(td);}body.append(tr);});}catch(e){out.textContent=e.message;body.replaceChildren();}} input.addEventListener('input',()=>{out.textContent='입력이 바뀌었습니다. 다시 계산하세요.';body.replaceChildren();});document.getElementById('xg-run').addEventListener('click',draw);for(const b of document.querySelectorAll('[data-xg-values]'))b.addEventListener('click',()=>{input.value=b.dataset.xgValues;draw();});draw(); }