{
  "schemaVersion": 1,
  "slug": "percentage-calculator",
  "category": "math",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "a990208980b4eed9d063f12f0b2919e540b51b91f6bb7b8eee1ac2ac9147e916",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/percentage-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": "p = y/x·100  |  y = x·p/100  |  x = y/(p/100)  |  Δ% = (b−a)/|a|·100  |  b' = a·(1+p/100)",
    "vars": [
      [
        "p",
        "Percentage, without the % sign"
      ],
      [
        "x",
        "Base / whole"
      ],
      [
        "y",
        "Part / resulting amount"
      ],
      [
        "a",
        "Starting value (percent change)"
      ],
      [
        "b",
        "Ending value (percent change)"
      ],
      [
        "b'",
        "Value after applying ±p% to a"
      ]
    ],
    "note": "Five modes: part÷whole, X% of Y, reverse whole, percent change, and increase/decrease by a percent. A zero whole, zero from-value, or zero percent in reverse mode is rejected. A percentage point is an absolute difference between two percentages, not the same as a percent change."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-27",
    "sources": [
      {
        "name": "NIST / SEMATECH e-Handbook — Percentages",
        "url": "https://www.itl.nist.gov/div898/handbook/mpc/section5/mpc55.htm"
      },
      {
        "name": "OpenStax Prealgebra 2e — Percent basics",
        "url": "https://openstax.org/books/prealgebra-2e/pages/6-introduction"
      }
    ],
    "basis": "Percentage = part ÷ whole × 100. Solving for the part uses whole × p/100; solving for the whole uses part ÷ (p/100). Percent change uses (new − old) ÷ |old| × 100. Applying a percent uses base × (1 + p/100). Zero denominators and a zero percent in reverse mode are rejected.",
    "limitations": "This page does compound successive percent changes only as separate steps; it does not convert percentage points to relative change automatically. Currency rounding and tax-inclusive price conventions are out of scope."
  },
  "contract": {
    "compute": "if(mode==='is'){if(!Number.isFinite(whole)||whole===0)return{__error:'inputError',percentage:null,amount:null,baseValue:null,result:null,difference:null};return{percentage:(part/whole)*100,amount:null,baseValue:null,result:null,difference:part-whole};}if(mode==='of'){if(!Number.isFinite(percent)||!Number.isFinite(whole))return{__error:'inputError',percentage:null,amount:null,baseValue:null,result:null,difference:null};return{percentage:null,amount:whole*(percent/100),baseValue:null,result:null,difference:null};}if(mode==='whole'){if(!Number.isFinite(percent)||percent===0||!Number.isFinite(part))return{__error:'inputError',percentage:null,amount:null,baseValue:null,result:null,difference:null};return{percentage:null,amount:null,baseValue:part/(percent/100),result:null,difference:null};}if(mode==='change'){if(!Number.isFinite(fromValue)||fromValue===0||!Number.isFinite(toValue))return{__error:'inputError',percentage:null,amount:null,baseValue:null,result:null,difference:null};const diff=toValue-fromValue;return{percentage:(diff/Math.abs(fromValue))*100,amount:null,baseValue:null,result:null,difference:diff};}if(mode==='changeTo'){if(!Number.isFinite(percent)||!Number.isFinite(base))return{__error:'inputError',percentage:null,amount:null,baseValue:null,result:null,difference:null};return{percentage:null,amount:null,baseValue:null,result:base*(1+percent/100),difference:base*(percent/100)};}return{__error:'inputError',percentage:null,amount:null,baseValue:null,result:null,difference:null};",
    "inputs": [
      {
        "name": "mode",
        "type": "select",
        "default": "is",
        "options": [
          {
            "value": "is"
          },
          {
            "value": "of"
          },
          {
            "value": "whole"
          },
          {
            "value": "change"
          },
          {
            "value": "changeTo"
          }
        ]
      },
      {
        "name": "part",
        "type": "number",
        "default": 25,
        "step": 0.01,
        "showWhen": {
          "mode": [
            "is",
            "whole"
          ]
        }
      },
      {
        "name": "whole",
        "type": "number",
        "default": 200,
        "step": 0.01,
        "showWhen": {
          "mode": [
            "of",
            "is"
          ]
        }
      },
      {
        "name": "percent",
        "type": "number",
        "default": 25,
        "step": 0.01,
        "showWhen": {
          "mode": [
            "of",
            "whole",
            "changeTo"
          ]
        }
      },
      {
        "name": "fromValue",
        "type": "number",
        "default": 80,
        "step": 0.01,
        "showWhen": {
          "mode": [
            "change"
          ]
        }
      },
      {
        "name": "toValue",
        "type": "number",
        "default": 100,
        "step": 0.01,
        "showWhen": {
          "mode": [
            "change"
          ]
        }
      },
      {
        "name": "base",
        "type": "number",
        "default": 100,
        "step": 0.01,
        "showWhen": {
          "mode": [
            "changeTo"
          ]
        }
      }
    ],
    "outputs": [
      {
        "name": "percentage",
        "precision": 2,
        "unit": "%",
        "optional": true,
        "showWhen": {
          "mode": [
            "is",
            "change"
          ]
        }
      },
      {
        "name": "amount",
        "precision": 2,
        "optional": true,
        "showWhen": {
          "mode": [
            "of"
          ]
        }
      },
      {
        "name": "baseValue",
        "precision": 2,
        "optional": true,
        "showWhen": {
          "mode": [
            "whole"
          ]
        }
      },
      {
        "name": "result",
        "precision": 2,
        "optional": true,
        "showWhen": {
          "mode": [
            "changeTo"
          ]
        }
      },
      {
        "name": "difference",
        "precision": 2,
        "optional": true,
        "showWhen": {
          "mode": [
            "change",
            "changeTo"
          ]
        }
      }
    ],
    "interpret": null
  }
}
