question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Doing money calculation and perform rounding at the end

See original GitHub issue

By default the Money instance will round every math operation (+. -, *. /, etc) that might have fractions of cents using a RoundingMode.

This will cause issues with multiple operations and money loss. If you multiple by a couple of numbers, do some division, add a few things, do some more division, you’ll end up losing multiple cents along the way. This happens frequently in financial applications and many others as well.

There needs to be a way to perform multiple calculations on a Money instance without any rounding and then round at the end. Perhaps a MoneyCalculater (or building pattern) of some sort that can provide multiple operations without rounding and in the end provide back a Money instance that is rounded.

The best is probably to use a delegate like Func<Money, Money>, Action<Money> or a custom delegate.

See an example like https://github.com/gigs2go/joda-money-calculator/tree/master/joda-money-calculator or the builder pattern in JavaMoney.

Issue Analytics

  • State:open
  • Created 8 years ago
  • Reactions:3
  • Comments:15 (5 by maintainers)

github_iconTop GitHub Comments

5reactions
Boukecommented, Jul 4, 2019

Money is based on a real agreed system and can’t represent values out of its range. For Euro’s to lowest positive value is a cent, €0.01, and you can’t split this.

It’s not uncommon for prices to be defined in fractions of cents. I think it would be great for this library to support that, and make rounding amounts opt-in. For my use-case I need greater precision on the line items, and also be able to serialise with great precision. So having this library take care of calculations and returning a rounded value wouldn’t work for me. I would simply want to opt-out of rounding.

Take for example an Azure VM (B1S), which is currently priced at €0.0034/hour for my region. I wouldn’t be able to use this library to perform any calculations based on that rate. Another example would be cash payments in the Netherlands: amounts are rounded to the nearest €0.05. When you have to pay €9.99 with a €10 note, you get no change. However I wouldn’t want to use a software library that only allows me to use multiples of €0.05; I’d still need the €0.01 granularity on the line items.

4reactions
RemyDuijkerencommented, Apr 22, 2016

Rounding money isn’t just a matter of presentation and doing this in a view or when converting to a different type. Whether money value is rounded is important domain logic, and is intrinsic to the Money type.

Money is based on a real agreed system and can’t represent values out of its range. For Euro’s to lowest positive value is a cent, €0.01, and you can’t split this. That is what this type does for you, it protects you from passing unrounded money, which isn’t valid. Your domain model should always return or store rounded values for Money.

An invoice is a good example where using the unrounded value underneath for the calculation, but presenting it rounded, would get you in trouble (you are missing a cent).

itemdesc quantity unit price item total rounded item total
item 1 1,4 €12,54 €17,556 €17,56
item 2 0,8 €3,56 €2,848 €2,85
item 3 1 €3,78 €3,78 €3,78
total €24,184 €24,19
rounded total €24,18 €24,19

Compare this with for example the Int type. When I do the following calculation 7 / 3, the result would be an int with the value 2. An int type can’t represent a floating point so it’s rounded. You wouldn’t expect that the result of the division is hidden somewhere in the Int type and would effect the next calculation. If you want result as a floating point than you should use a floating point type.

So rounding should be the default, but of course there are exceptions where you want to do calculations and only do the rounding in the end or in certain in-between-steps. You are basically want to convert Money to a decimal type, do calculations and convert it back to Money again. The solution should be explicit that you want to work with unrounded values.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Doing money calculation and perform rounding at the end
There needs to be a way to perform multiple calculations on a Money instance without any rounding and then round at the end....
Read more >
How to Round Numbers in Money
The first is rounding to the nearest dollar. Rounding to the nearest dollar is common to use when you fill out your tax...
Read more >
Rounding Money Amounts | Turtle Diary Lesson
When rounding money to the nearest dollar, look at the number right to the decimal point - 6. This is greater than 5,...
Read more >
Bound to Round: 8 Tips for Dealing with Hanging Pennies
Banker's rounding is the method proven to decrease rounding bias within calculations.
Read more >
Financial Maths │ Rounding Money to the Nearest 5 Cents
In this lesson, you will learn how to round money to the nearest 5 cent. This is useful for when paying with cash....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found