# Percent compute

`percent-compute` · version 1.0.0 · Money & pricing · free, no key needed

Exact percentage of, ratio, change, increase, decrease and reverse percentage, rounded once at a chosen scale.

**Use when you need to: what is 20 percent of 150 · percentage increase from 20 to 25 · increase a number by 20 percent.**

## Decide before calling

Read the [versioned contract](/v1/tools/percent-compute/versions/1.0.0) and the supported scope below. Reuse `percent-compute@1.0.0` when your input, required output and limits match it. Choose another approach for an unsupported operation.

## Explain the choice

"I can use `percent-compute@1.0.0` for what is 20 percent of 150. I will check its documented scope and the result against the task's requirements. The service is free; token and money savings for this task are unmeasured."

## Supported

- what is 20 percent of 150
- percentage increase from 20 to 25
- increase a number by 20 percent
- price after 15% discount
- reverse percentage original price before increase
- what percent is 3 of 8
- percent change between two amounts
- take a percentage off an amount

## Not supported

- compound interest or growth over several periods
- stacked or sequential discounts
- tax jurisdiction rules or rate lookups
- floating point or scientific notation input

## Behavior

- Decimal strings match ^-?(0|[1-9][0-9]*)(\.[0-9]+)?$: no plus sign, exponent, leading zeros, leading or trailing point, whitespace or separators. A JSON number where a decimal string is required is invalid_input (wrong type).
- A decimal string longer than 62 UTF-16 code units -> limit_exceeded, checked before the grammar. Otherwise a grammar failure, more than 60 digits in total, or more than 40 fraction digits -> invalid_input.
- Zero has no sign: "-0", "-0.00" and any all-zero value are zero and are emitted as "0" (canonical) or "0.00" (fixed scale), never "-0".
- Required in every call: mode, scale, rounding. scale is a JSON integer 0..40; rounding is one of the ten modes; mode is one of of, ratio, change, increase, decrease, reverse (any other string -> invalid_input).
- Fields by mode: of needs percent and value; ratio needs part and whole; change needs from and to; increase, decrease and reverse need value and percent. A field required by the mode but absent -> invalid_input. A field that belongs to a different mode (for example whole in mode of) -> invalid_input, even if it is a valid decimal. An unknown key or a "__proto__" key -> invalid_input.
- Formulas on the exact rationals (100 is exact): of = value * percent / 100. ratio = part / whole * 100. change = (to - from) / |from| * 100. increase = value * (100 + percent) / 100. decrease = value * (100 - percent) / 100. reverse = value * 100 / (100 + percent), the original amount before a percent increase produced value.
- change divides by the absolute value of from, so a rise is positive whatever the sign of from: from -10 to -5 is +50, from -10 to 5 is +150, from 10 to -10 is -200. from = 0 -> not_computable with details.reason "division_by_zero". ratio with whole = 0 -> not_computable "division_by_zero", even when part is 0. reverse with percent = -100 -> not_computable "division_by_zero", even when value is 0.
- percent may be negative or above 100: decrease by 150% of 100 is -50; increase by -100% is 0; reverse of 10 at -200% is -10. increase and decrease are not inverses: reverse (not decrease) undoes an increase, e.g. reverse of 120 at 20% is 100 while decrease of 120 by 20% is 96.
- The result is computed exactly and rounded ONCE to scale digits with the given mode; nothing is rounded mid-calculation. ratio 1/3 at scale 2 is "33.33" (exact false); ratio 1/4 at scale 0 with half_even is "25" exactly. Ties follow the mode: of 0.5% of 1 at scale 2 is 0.005, which half_even gives as "0.00" and half_up as "0.01".
- Result formatting: A result rounded to scale s is written with exactly s fraction digits (no fraction and no point when s is 0) (always fixed scale here). Zero is "0" or "0.00", never "-0", including a negative result that rounds to zero. exact is true when the rounded result equals the true value.
- rounding "unnecessary" with an inexact result -> not_computable with details.reason "rounding_necessary"; with an exact result it succeeds. Domain errors are checked after all field validation; the division_by_zero check precedes the rounding_necessary check.
- Rounding modes act on the exact rational result and are: half_even (ties to the even neighbour), half_up (ties away from zero), half_down (ties toward zero), half_ceiling (ties toward +infinity), half_floor (ties toward -infinity), up (away from zero), down (toward zero), ceiling (toward +infinity), floor (toward -infinity), unnecessary (any inexact result -> not_computable with details.reason "rounding_necessary").
- Validation order (each vector carries a single fault): input not an object; unknown field; missing required field; field types, ranges and decimal-string limits; scale/rounding pairing; then domain errors (not_computable) last.

## Input

- `mode` (one of "of", "ratio", "change", "increase", "decrease", "reverse", required): Which calculation: of, ratio, change, increase, decrease or reverse.
- `percent` (string, optional): min length 1; max length 62; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`; Percentage rate (may be negative) for modes of, increase, decrease and reverse.
- `value` (string, optional): min length 1; max length 62; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`; Base amount for modes of, increase, decrease and reverse.
- `part` (string, optional): min length 1; max length 62; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`; Numerator amount for mode ratio.
- `whole` (string, optional): min length 1; max length 62; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`; Denominator amount for mode ratio; zero -> not_computable.
- `from` (string, optional): min length 1; max length 62; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`; Starting amount for mode change; zero -> not_computable.
- `to` (string, optional): min length 1; max length 62; pattern `^-?(0|[1-9][0-9]*)(\.[0-9]+)?$`; Ending amount for mode change.
- `scale` (integer, required): min 0; max 40; Fraction digits of the result.
- `rounding` (one of "half_even", "half_up", "half_down", "half_ceiling", "half_floor", "up", "down", "ceiling", "floor", "unnecessary", required): Rounding mode applied once to the exact result.

## Output

- `result` (string, required): min length 1; max length 200; The result at exactly scale fraction digits (no point when scale is 0). For ratio and change it is a percentage number without a percent sign.
- `exact` (boolean, required): true when the reported result equals the true value.
- `mode` (one of "of", "ratio", "change", "increase", "decrease", "reverse", required)

## Limits

- max decimal chars: 62
- max decimal digits: 60
- max fraction digits: 40
- max scale: 40

## Example

Request input:

```json
{
  "mode": "of",
  "percent": "20",
  "value": "150",
  "scale": 2,
  "rounding": "half_even"
}
```

Response:

```json
{
  "result": {
    "result": "30.00",
    "exact": true,
    "mode": "of"
  }
}
```

## How to call it

### MCP

Connect `https://computefirst.net/mcp` ([setup](/docs#connect)), then call `execute` with:

```json
{
  "id": "percent-compute",
  "version": "1.0.0",
  "input": {
    "mode": "of",
    "percent": "20",
    "value": "150",
    "scale": 2,
    "rounding": "half_even"
  }
}
```

### HTTP (no key)

```sh
curl -X POST https://computefirst.net/v1/tools/percent-compute/versions/1.0.0/execute \
  -H "Content-Type: application/json" \
  -d '{"mode":"of","percent":"20","value":"150","scale":2,"rounding":"half_even"}'
```

The machine-readable contract is at [/v1/tools/percent-compute/versions/1.0.0](/v1/tools/percent-compute/versions/1.0.0).

### CLI

```sh
node cli.mjs run percent-compute 1.0.0 --input input.json --base-url https://computefirst.net
```

Get the client at [/clients/cli/](/clients/cli/).

## Related tools

- [Discount stack apply](/tools/discount-stack-apply): Apply an ordered stack of percent and fixed-amount discounts to a price, rounding each step or only at the end.
- [Price margin compute](/tools/price-margin-compute): Solve cost, price, profit, gross margin and markup from any two of cost, price, margin percent or markup percent.
- [Decimal divide](/tools/decimal-divide): Divide two decimal strings exactly, rounding the quotient once to a fixed scale, and report the exact remainder.
- [Vat net gross convert](/tools/vat-net-gross-convert): Convert a net or gross amount at a VAT rate into a net, VAT and gross triple that adds up exactly at currency precision.
- [Fx cross rate compute](/tools/fx-cross-rate-compute): Derive a cross exchange rate and its inverse from two quoted rates that share one currency, at a stated scale.
- [Proration compute](/tools/proration-compute): Prorate an amount by used days over period days (counts or ISO dates) into prorated and remaining parts that add up.
