Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add complete set of arithmetic operations #4

Open
samuel-emrys opened this issue May 15, 2021 · 0 comments
Open

Add complete set of arithmetic operations #4

samuel-emrys opened this issue May 15, 2021 · 0 comments

Comments

@samuel-emrys
Copy link

samuel-emrys commented May 15, 2021

It would be good to be able to use money objects arithmetically unimpeded using math libraries such as xtensor or DataFrame. To provide a concrete example of something that's not currently supported, would be finding the standard deviation of a timeseries of money objects:

std::vector<money> population {{5.0, currency::USD}, {10.0, currency::USD}, {30.0, currency::USD}};
money std_dev = sqrt((1/population.size()) * sum(pow(population - mean(population)), 2.0));

The element of this calculation not currently supported is the pow operation. This can't be easily computed using addition (though it can), but providing the multiplication overload for two money types would drastically improve the ease of a calculation such as this:

template <typename TValue1>
inline auto operator*(money<TValue1> const & lhs, money<TValue1> const & rhs)

Understandably only the TValue2 overload has been implemented for this, as the result of money * money doesn't necessarily make a lot of sense - the result isn't necessarily a sensible value that represents money. However, these kinds of operations are essential in performing any kind of data analysis.

Additional overloads that would be useful:

  • operator*(TValue2, money) - so that the float doesn't have to be the second argument - i.e. moneyVal * 2.0 and 2.0 * moneyVal are both valid statements
  • operator/(money, money)
  • operator/(TValue2, money)
  • operator%(money, money)
  • operator%(TValue2, money)
  • operator+=(TValue2)
  • operator+=(money)
  • operator-=(TValue2)
  • operator-=(money)
  • operator*=(TValue2)
  • operator*=(money)
  • operator\=(TValue2)
  • operator\=(money)
  • operator<<(stream, money) - It would be good to be able to convert money objects to strings for debugging/output

It may also be necessary to implement proxy functions for some of the std math functions: std::pow, std::sqrt, std::sin, etc.

One complication to consider here is that I think it's probably prudent to ensure that these operations are all homogeneous. You could have heterogeneous calculations in which you do conversions between currencies on the fly, but especially for the operations in which a new money object is generated, there would be ambiguity around which currency the result should be denominated in. The calculation is exactly the same, the result is exactly the same, so it actually doesn't matter which currency is assigned to the object, but for the sake of consistency and type safety I think that it would be prudent to throw an error if the currencies of the money objects in a multiplication or a division are not the same. I can see that you've done this for the equality operator so it seems that this perspective is consistent with yours.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant