Skip to content

Percentages & Tax

Percentage math is where float error is most visible to end users — a receipt that's one cent off is a support ticket. Keep everything in BigDecimal and round at the end.

A percentage of a value

A percent is just a multiplication by p / 100:

js
import { Big, RoundingMode } from 'bigdecimal.js'

function percentOf(value, percent) {
  return Big(value).multiply(percent).divide(100, 20, RoundingMode.HALF_UP).stripTrailingZeros()
}

percentOf('250', '8.25').toString() // '20.625'

Since /100 always terminates, you can also just shift or divide exactly:

js
Big('250').multiply('8.25').divide(100, 4, RoundingMode.HALF_UP).toString() // '20.6250'

Adding tax

js
const net = Big('49.99')
const vat = Big('0.19') // 19%

const tax = net.multiply(vat)                       // '9.4981'
const gross = net.add(tax)                          // '59.4881'

gross.setScale(2, RoundingMode.HALF_UP).toString()  // '59.49'
Ctrl / ⌘ + Enter

Extracting tax from a gross amount

Given a tax-inclusive total, recover the net and the tax portion. This division doesn't terminate, so give it a scale:

js
const gross = Big('59.49')
const rate = Big('0.19')

// net = gross / (1 + rate)
const net = gross.divide(Big(1).add(rate), 2, RoundingMode.HALF_UP) // '49.99'
const tax = gross.subtract(net)                                     // '9.50'

Discounts

js
function applyDiscount(price, percentOff) {
  const factor = Big(1).subtract(Big(percentOff).divide(100, 10, RoundingMode.HALF_UP))
  return Big(price).multiply(factor).setScale(2, RoundingMode.HALF_UP)
}

applyDiscount('79.99', '15').toString() // '67.99'

Compound growth

Percentages compound with pow. Interest of 5% for 3 periods:

js
const principal = Big('1000')
const growth = Big('1.05')

principal.multiply(growth.pow(3)).setScale(2, RoundingMode.HALF_UP).toString() // '1157.63'
Ctrl / ⌘ + Enter

Round for display, keep precision for math

Round to 2 decimals when you show a value, but if you feed a result back into the next calculation, keep the full-precision BigDecimal — re-rounding at each step drifts.

Released under the Apache-2.0 License.