{
  "schemaVersion": 1,
  "slug": "weighted-average-calculator",
  "category": "math",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "7ec0c8c10009eaadb81cb012c152745be2259b04b05244d5bb7f07beec931fbf",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/weighted-average-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "x̄_w = Σ (x_i × w_i) ÷ Σ w_i",
    "vars": [
      [
        "x_i",
        "Values list"
      ],
      [
        "w_i",
        "Weights list"
      ],
      [
        "n",
        "Paired count"
      ],
      [
        "x̄_w",
        "Weighted average"
      ]
    ],
    "note": "Lists must have equal lengths; entries pair by index. Weights must be nonnegative with Σw>0. Separate with commas/spaces for decimal-point values; with decimal commas, use semicolons between entries (commas within numbers are converted to decimal points). Inputs are limited to 1,000 entries."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const parseList=raw=>{const s=String(raw).trim();if(!s)return[];const decimalComma=s.includes(';');const parts=s.split(decimalComma?/[;\\s]+/ : /[,\\s]+/).filter(Boolean);return parts.map(v=>decimalComma?v.replace(',','.'):v)};const xs0=parseList(values),ws0=parseList(weights);const good=a=>a.length>0&&a.length<=1000&&a.every(v=>/^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?$/i.test(v)&&Number.isFinite(Number(v)));if(!good(xs0)||!good(ws0)||xs0.length!==ws0.length)return{weightedAverage:null,totalWeight:null,simpleAverage:null,count:null,__error:'inputError'};const xs=xs0.map(Number),ws=ws0.map(Number),den=ws.reduce((a,b)=>a+b,0);if(ws.some(w=>w<0)||!Number.isFinite(den)||den<=0)return{weightedAverage:null,totalWeight:null,simpleAverage:null,count:null,__error:'inputError'};let num=0,sum=0;for(let i=0;i<xs.length;i++){num+=xs[i]*ws[i];sum+=xs[i]}const weightedAverage=num/den,simpleAverage=sum/xs.length;if(!Number.isFinite(num)||!Number.isFinite(sum)||!Number.isFinite(weightedAverage)||!Number.isFinite(simpleAverage))return{weightedAverage:null,totalWeight:null,simpleAverage:null,count:null,__error:'inputError'};return{weightedAverage,totalWeight:den,simpleAverage,count:xs.length};",
    "inputs": [
      {
        "name": "values",
        "type": "text",
        "default": "85, 92, 78",
        "step": 1
      },
      {
        "name": "weights",
        "type": "text",
        "default": "0.3, 0.5, 0.2",
        "step": 1
      }
    ],
    "outputs": [
      {
        "name": "weightedAverage",
        "precision": 4,
        "unit": ""
      },
      {
        "name": "totalWeight",
        "precision": 4,
        "unit": ""
      },
      {
        "name": "simpleAverage",
        "precision": 4,
        "unit": ""
      },
      {
        "name": "count",
        "precision": 0,
        "unit": ""
      }
    ],
    "interpret": null
  }
}
