Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A Money type for the CLR

, 18 Mar 2013 Ms-PL
A convenient, high-performance money structure for the CLR which handles arithmetic operations, currency types, formatting, and careful distribution and rounding without loss.
moneytype.zip
Money
lib
xunit.console.clr4.exe
xunit.console.clr4.pdb
xunit.console.clr4.x86.exe
xunit.console.clr4.x86.pdb
xunit.console.exe
xunit.console.pdb
xunit.console.x86.exe
xunit.console.x86.pdb
xunit.dll
xunit.dll.tdnet
xunit.extensions.dll
xunit.extensions.pdb
xunit.gui.clr4.exe
xunit.gui.clr4.pdb
xunit.gui.clr4.x86.exe
xunit.gui.clr4.x86.pdb
xunit.gui.exe
xunit.gui.pdb
xunit.gui.x86.exe
xunit.gui.x86.pdb
xunit.installer.exe
xunit.installer.pdb
xunit.pdb
xunit.runner.msbuild.dll
xunit.runner.msbuild.pdb
xunit.runner.tdnet.dll
xunit.runner.tdnet.pdb
xunit.runner.utility.dll
xunit.runner.utility.pdb
xunitext.dll
xunitext.nunit.dll
xunitext.runner.jetbrains.dll
xunitext.runner.msbuild.dll
xunitext.runner.tdnet.dll
xunitext35.dll
src
Money
Money.sln.DotSettings.user
Money.Tests
bin
Debug
Money.dll
Money.pdb
Money.Tests.dll
Money.Tests.pdb
xunit.dll
xunit.pdb
obj
Debug
DesignTimeResolveAssemblyReferencesInput.cache
Money.Tests.csprojResolveAssemblyReference.cache
Money.Tests.dll
Money.Tests.pdb
TempPE
Properties
Money.v11.suo
bin
Debug
Money.dll
Money.pdb
obj
Debug
DesignTimeResolveAssemblyReferencesInput.cache
Money.csprojResolveAssemblyReference.cache
Money.dll
Money.pdb
TempPE
Properties
using System;

namespace System
{
    public class MoneyDistributor
    {
        private readonly Money _toDistribute;
        private readonly FractionReceivers _receiver;
        private readonly RoundingPlaces _precision;
        private Money _distributedTotal;
        private Decimal[] _distribution;

        public MoneyDistributor(Money amountToDistribute,
                                FractionReceivers receiver,
                                RoundingPlaces precision)
        {
            _toDistribute = amountToDistribute;
            _receiver = receiver;
            _precision = precision;
        }

        public Money[] Distribute(params Decimal[] distribution)
        {
            _distribution = distribution;
            throw new NotImplementedException();
        }

        public Money[] Distribute(Int32 count)
        {
            if (count < 1)
            {
                throw new ArgumentOutOfRangeException("count",
                                                      count,
                                                      "The number of divisions " +
                                                      "which should be made " +
                                                      "must be greater than 0.");
            }

            return Distribute(1 / count);
        }

        public Money[] Distribute(decimal distribution)
        {
            if (distribution > 1 || distribution <= 0)
            {
                throw new ArgumentOutOfRangeException("distribution",
                                                      distribution,
                                                      "A uniform distribution must be " +
                                                      "greater than 0 and " +
                                                      "less than or equal to 1.0");
            }

            _distribution = new decimal[1];
            _distribution[0] = distribution;

            var distributionCount = (Int32)Math.Floor(1 / distribution);
            var result = new Money[distributionCount];

            _distributedTotal = new Money(0, _toDistribute.Currency);
            decimal quantum = (Decimal)Math.Pow(10, -(Int32)_precision);

            for (int i = 0; i < distributionCount; i++)
            {
                var toDistribute = _toDistribute;
                var part = toDistribute / distributionCount;
                part = Math.Round(part - (0.5M * quantum),
                                  (Int32)_precision,
                                  MidpointRounding.AwayFromZero);
                result[i] = part;
                _distributedTotal += part;
            }

            var remainder = _toDistribute - _distributedTotal;

            switch (_receiver)
            {
                case FractionReceivers.FirstToLast:
                    for (var i = 0; i < remainder / quantum; i++)
                    {
                        result[i] += quantum;
                        _distributedTotal += quantum;
                    }
                    break;
                case FractionReceivers.LastToFirst:
                    for (var i = (Int32)(remainder / quantum); i > 0; i--)
                    {
                        result[i] += quantum;
                        _distributedTotal += quantum;
                    }
                    break;
                case FractionReceivers.Random:
                    // need the mersenne twister code... System.Random isn't good enough
                    throw new NotImplementedException();
                default:
                    break;
            }

            if (_distributedTotal != _toDistribute)
            {
                throw new MoneyAllocationException(_toDistribute,
                                                   _distributedTotal,
                                                   _distribution);
            }

            return result;
        }

        public Money[] Distribute(decimal distribution1, decimal distribution2)
        {
            var distributionSum = distribution1 + distribution2;

            if (distributionSum <= 0 || distributionSum > 1)
            {
                throw new ArgumentException("The sum of the distributions" +
                                            "must be greater than 0 and " +
                                            "less than or equal to 1");
            }

            var result = new Money[2];
            throw new NotImplementedException();
        }

        public Money[] Distribute(decimal distribution1,
                                  decimal distribution2,
                                  decimal distribution3)
        {
            throw new NotImplementedException();
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

codekaizen
Architect
United States United States
I'm a software engineer with 25 years of experience in areas from game and simulation development, enterprise development, systems management, machine learning, real-time and embedded systems development and geospaitial systems development.
 
You can find more of my work at http://www.codeplex.com and my articles at http://vectordotnet.blogspot.com/ and http://dotnoted.spaces.live.com.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 18 Mar 2013
Article Copyright 2008 by codekaizen
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid