Skip to content

Repository files navigation

ringgit

Malaysian money, handled the way the rules say. Cash rounding to 5 sen per Bank Negara, SST by category, and amounts in words for cheques and invoices. Everything is Decimal; floats are refused at the door.

$ ringgit round 12.33
RM12.33 -> RM12.35 (rounding +RM0.02)
$ ringgit words 1234.50
Ringgit Malaysia: Seribu Dua Ratus Tiga Puluh Empat Dan Lima Puluh Sen Sahaja
$ ringgit sst 33.33 fnb
net RM33.33
sst RM2.00
gross RM35.33
cash RM35.35
pip install ringgit

No dependencies. Python 3.10+.

Why

Three things go wrong in almost every Malaysian invoicing codebase:

  1. Money in floats.0.1 + 0.2 is not 0.3, and a total that is off by a sen fails reconciliation. ringgit takes str, int or Decimal and raises TypeError on a float instead of rounding it quietly.
  2. The 5-sen rule done wrong. Since 1 April 2008 the total of a cash bill is rounded to the nearest 5 sen: 1 and 2 sen down, 3 and 4 up to 5, 6 and 7 down to 5, 8 and 9 up to 10. It applies to the cash total only, not to each line and not to card or transfer payments. People round every item, or round electronic payments, or use a generic "round to nearest 0.05" that behaves differently at the edges.
  3. "The SST rate." There is not one. Service tax is 8% standard and 6% for food and beverage, telecommunications, parking, logistics and, since 1 January 2026, industrial rental. Sales tax is 5% or 10% by tariff line, with exempt goods at 0%. A single constant is the wrong answer.

Use it

fromringgitimportRM, round_cash, sst, to_wordstotal=RM("10.10") +RM("0.20") +"0.03"# RM10.33total.cash() # RM10.35 — what the customer hands overstr(total) # 'RM10.33'round_cash("12.38") # Decimal('12.40')sst("100", "service") # Decimal('8.00')sst("100", "fnb") # Decimal('6.00')sst("100", Decimal("0.07")) # an explicit rate, when you mustto_words("1500") # 'Ringgit Malaysia: Seribu Lima Ratus Sahaja'to_words("1500", "en") # 'Ringgit Malaysia One Thousand Five Hundred Only'

The words follow cheque convention: Ringgit Malaysia: ... Sahaja, with se- before puluh, belas, ratus and ribu (sepuluh, sebelas, seratus, seribu) and satu before juta and bilion.

Sources

  • Rounding: Bank Negara Malaysia, Rounding Mechanism, effective 1 April 2008.
  • SST: Royal Malaysian Customs Department, MySST. Rates as of 1 January 2026.

47 tests, including the full sen-ending table for the rounding rule and the awkward Malay numerals (sebelas, seratus satu, satu juta).

Licence

MIT.

About

Malaysian money done right: BNM 5-sen cash rounding, SST rates, and ringgit-to-Malay-words for invoices and cheques. Decimal only, no floats.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages