Last active
August 29, 2015 14:24
-
-
Save MovGP0/40a9cca249ab2e385e53 to your computer and use it in GitHub Desktop.
Money and Percent types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.Serialization; | |
using System.Xml.Serialization; | |
namespace CN.Lib.Types | |
{ | |
[Serializable] | |
[DataContract] | |
public struct Money : IEquatable<Money>, IComparable<Money>, IFormattable, ISerializable, IConvertible | |
{ | |
[DataMember(Name = "amount", IsRequired = true)] | |
[XmlText] | |
private readonly decimal _amount; | |
public Money(decimal amount) | |
{ | |
_amount = amount; | |
} | |
public static Money Zero | |
{ | |
get { return new Money(0m); } | |
} | |
public static Money Cent | |
{ | |
get { return new Money(SiPrefix.Centi); } | |
} | |
public static Money Million | |
{ | |
get { return new Money(SiPrefix.Mega); } | |
} | |
public static Money Thousand | |
{ | |
get { return new Money(SiPrefix.Kilo); } | |
} | |
public static Money Hundred | |
{ | |
get { return new Money(SiPrefix.Hecto); } | |
} | |
public static Money One | |
{ | |
get { return new Money(decimal.One); } | |
} | |
public static Money MinusOne | |
{ | |
get { return new Money(decimal.MinusOne); } | |
} | |
public static Money MinValue | |
{ | |
get { return new Money(decimal.MinValue); } | |
} | |
public static Money MaxValue | |
{ | |
get { return new Money(decimal.MaxValue); } | |
} | |
public int CompareTo(Money other) | |
{ | |
return _amount.CompareTo(other._amount); | |
} | |
public bool Equals(Money other) | |
{ | |
return _amount == other._amount; | |
} | |
public string ToString(string format, IFormatProvider formatProvider) | |
{ | |
return _amount.ToString(format, formatProvider); | |
} | |
public static implicit operator Money(decimal amount) | |
{ | |
return new Money(amount); | |
} | |
public static explicit operator decimal(Money money) | |
{ | |
return money._amount; | |
} | |
public decimal ToDecimal() | |
{ | |
return _amount; | |
} | |
public override bool Equals(object obj) | |
{ | |
if (ReferenceEquals(null, obj)) | |
{ | |
return false; | |
} | |
return obj is Money && Equals((Money) obj); | |
} | |
public override int GetHashCode() | |
{ | |
return _amount.GetHashCode(); | |
} | |
public static bool operator ==(Money left, Money right) | |
{ | |
return left.Equals(right); | |
} | |
public static bool operator <(Money left, Money right) | |
{ | |
return left._amount < right._amount; | |
} | |
public static bool operator >(Money left, Money right) | |
{ | |
return left._amount > right._amount; | |
} | |
public static bool operator <=(Money left, Money right) | |
{ | |
return left._amount <= right._amount; | |
} | |
public static bool operator >=(Money left, Money right) | |
{ | |
return left._amount >= right._amount; | |
} | |
public static bool operator !=(Money left, Money right) | |
{ | |
return !left.Equals(right); | |
} | |
public static Money operator -(Money amount) | |
{ | |
return -(amount._amount); | |
} | |
public static Percent operator /(Money numerator, Money denumerator) | |
{ | |
return new Percent(numerator._amount/denumerator._amount); | |
} | |
public static Money operator +(Money left, Money right) | |
{ | |
return new Money(left._amount + right._amount); | |
} | |
public static Money operator -(Money left, Money right) | |
{ | |
return new Money(left._amount - right._amount); | |
} | |
public static Money operator *(Money value, decimal scalarValue) | |
{ | |
return new Money(value._amount*scalarValue); | |
} | |
public static Money operator *(Money value, Percent percent) | |
{ | |
return new Money(value._amount*(decimal) percent); | |
} | |
public static Money operator *(Percent percent, Money value) | |
{ | |
return new Money(value._amount*(decimal) percent); | |
} | |
public static Money operator *(decimal scalarValue, Money value) | |
{ | |
return new Money(value._amount*scalarValue); | |
} | |
public static Money operator /(Money value, decimal scalarValue) | |
{ | |
return new Money(value._amount/scalarValue); | |
} | |
public override string ToString() | |
{ | |
return string.Format("{0:0.00}", Math.Round(_amount, 2, MidpointRounding.AwayFromZero)); | |
} | |
public string ToString(string format) | |
{ | |
return _amount.ToString(format); | |
} | |
public string ToString(IFormatProvider formatProvider) | |
{ | |
return _amount.ToString(formatProvider); | |
} | |
#region ISerializable | |
/// <summary> | |
/// Deserialization constructor | |
/// </summary> | |
/// <param name="info"></param> | |
/// <param name="context"></param> | |
public Money(SerializationInfo info, StreamingContext context) | |
{ | |
_amount = info.GetDecimal("amount"); | |
} | |
/// <summary> | |
/// Serialization method | |
/// </summary> | |
/// <param name="info"></param> | |
/// <param name="context"></param> | |
public void GetObjectData(SerializationInfo info, StreamingContext context) | |
{ | |
info.AddValue("amount", _amount); | |
} | |
#endregion | |
#region IConvertible | |
public TypeCode GetTypeCode() | |
{ | |
return TypeCode.Decimal; | |
} | |
public bool ToBoolean(IFormatProvider provider) | |
{ | |
return Convert.ToBoolean(_amount, provider); | |
} | |
public byte ToByte(IFormatProvider provider) | |
{ | |
return Convert.ToByte(_amount, provider); | |
} | |
public char ToChar(IFormatProvider provider) | |
{ | |
return Convert.ToChar(_amount, provider); | |
} | |
public DateTime ToDateTime(IFormatProvider provider) | |
{ | |
return Convert.ToDateTime(_amount, provider); | |
} | |
public decimal ToDecimal(IFormatProvider provider) | |
{ | |
return Convert.ToDecimal(_amount, provider); | |
} | |
public double ToDouble(IFormatProvider provider) | |
{ | |
return Convert.ToDouble(_amount, provider); | |
} | |
public short ToInt16(IFormatProvider provider) | |
{ | |
return Convert.ToInt16(_amount, provider); | |
} | |
public int ToInt32(IFormatProvider provider) | |
{ | |
return Convert.ToInt32(_amount, provider); | |
} | |
public long ToInt64(IFormatProvider provider) | |
{ | |
return Convert.ToInt64(_amount, provider); | |
} | |
public sbyte ToSByte(IFormatProvider provider) | |
{ | |
return Convert.ToSByte(_amount, provider); | |
} | |
public float ToSingle(IFormatProvider provider) | |
{ | |
return Convert.ToSingle(_amount, provider); | |
} | |
public object ToType(Type conversionType, IFormatProvider provider) | |
{ | |
return Convert.ChangeType(_amount, conversionType, provider); | |
} | |
public ushort ToUInt16(IFormatProvider provider) | |
{ | |
return Convert.ToUInt16(_amount, provider); | |
} | |
public uint ToUInt32(IFormatProvider provider) | |
{ | |
return Convert.ToUInt32(_amount, provider); | |
} | |
public ulong ToUInt64(IFormatProvider provider) | |
{ | |
return Convert.ToUInt64(_amount, provider); | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace CN.Lib.Types | |
{ | |
public static class MoneyExtensions | |
{ | |
public static Money Sum(this IEnumerable<Money> amounts) | |
{ | |
var sum = new Money(0m); | |
return amounts.Aggregate(sum, (current, ammount) => current + ammount); | |
} | |
public static Money Sum<T>(this IEnumerable<T> amounts, Func<T, Money> func) | |
{ | |
return amounts.Select(func).Sum(); | |
} | |
public static Money Sum(this IEnumerable<Money> amounts, Func<Money, bool> func) | |
{ | |
return amounts.Where(func).Sum(); | |
} | |
public static Money Average(this IEnumerable<Money> amounts) | |
{ | |
return amounts.Select(v => (decimal)v).Average(); | |
} | |
/// <summary> | |
/// Absolute value. | |
/// </summary> | |
/// <param name="percentage"></param> | |
/// <returns></returns> | |
public static Money Abs(this Money percentage) | |
{ | |
return Math.Abs((decimal)percentage); | |
} | |
/// <summary> | |
/// Rounding to cent precision. | |
/// </summary> | |
/// <param name="amount"></param> | |
/// <returns></returns> | |
public static Money Round(this Money amount) | |
{ | |
return Math.Round((decimal) amount, 2); | |
} | |
public static Money Round(this Money amount, int decimals) | |
{ | |
return Math.Round((decimal) amount, decimals); | |
} | |
/// <summary> | |
/// Rounding to cent precision. | |
/// </summary> | |
/// <param name="amount"></param> | |
/// <returns></returns> | |
public static Money Round(this Money amount, MidpointRounding rounding) | |
{ | |
return Math.Round((decimal) amount, 2, rounding); | |
} | |
public static Money Round(this Money amount, int decimals, MidpointRounding rounding) | |
{ | |
return Math.Round((decimal) amount, decimals, rounding); | |
} | |
public static int Sign(this Money amount) | |
{ | |
return Math.Sign((decimal)amount); | |
} | |
/// <summary> | |
/// Compares if a given value is within 6 significant digits to <value>0m</value>. | |
/// </summary> | |
/// <param name="value"></param> | |
/// <returns></returns> | |
public static bool IsApproximatelyZero(this Money value) | |
{ | |
return IsApproximately(value, Money.Zero); | |
} | |
/// <summary> | |
/// Compares two decimal numbers with a precision of 6 significant digits. | |
/// </summary> | |
/// <param name="value"></param> | |
/// <param name="other"></param> | |
/// <returns></returns> | |
public static bool IsApproximately(this Money value, Money other) | |
{ | |
Money ε = 0.000001m; | |
return value.IsApproximately(other, ε); | |
} | |
/// <summary> | |
/// Compares if two decimal numbers are within a given difference. | |
/// </summary> | |
/// <param name="value"></param> | |
/// <param name="other"></param> | |
/// <param name="epsilon">The maximal difference between the two numbers.</param> | |
/// <returns></returns> | |
public static bool IsApproximately(this Money value, Money other, Money epsilon) | |
{ | |
return value < (other + epsilon) | |
&& value > (other - epsilon); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.Serialization; | |
using System.Xml.Serialization; | |
namespace CN.Lib.Types | |
{ | |
[Serializable] | |
[DataContract(Name = "Percent")] | |
public struct Percent : IEquatable<Percent>, IComparable<Percent>, IFormattable, IConvertible | |
{ | |
[DataMember(Name="percentage", IsRequired = true)] | |
[XmlText] | |
private readonly decimal _value; | |
public static Percent Zero | |
{ | |
get { return new Percent(0m); } | |
} | |
public static Percent Hundred | |
{ | |
get { return new Percent(1m); } | |
} | |
public static Percent MaxValue | |
{ | |
get { return new Percent(decimal.MaxValue); } | |
} | |
public static Percent MinValue | |
{ | |
get { return new Percent(decimal.MinValue); } | |
} | |
public Percent(decimal value) | |
{ | |
_value = value; | |
} | |
public bool Equals(Percent other) | |
{ | |
return _value.Equals(other._value); | |
} | |
public decimal ToDecimal() | |
{ | |
return _value; | |
} | |
public static explicit operator decimal(Percent percent) | |
{ | |
return percent._value; | |
} | |
public static implicit operator Percent(decimal value) | |
{ | |
return new Percent(value); | |
} | |
public int CompareTo(Percent other) | |
{ | |
return _value.CompareTo(other._value); | |
} | |
public override bool Equals(object obj) | |
{ | |
if (ReferenceEquals(null, obj)) | |
{ | |
return false; | |
} | |
return obj is Percent && Equals((Percent) obj); | |
} | |
public override int GetHashCode() | |
{ | |
return _value.GetHashCode(); | |
} | |
public static bool operator ==(Percent left, Percent right) | |
{ | |
return left.Equals(right); | |
} | |
public static bool operator <(Percent left, Percent right) | |
{ | |
return left._value < right._value; | |
} | |
public static bool operator >(Percent left, Percent right) | |
{ | |
return left._value > right._value; | |
} | |
public static bool operator <=(Percent left, Percent right) | |
{ | |
return left._value <= right._value; | |
} | |
public static bool operator >=(Percent left, Percent right) | |
{ | |
return left._value >= right._value; | |
} | |
public static bool operator !=(Percent left, Percent right) | |
{ | |
return !left.Equals(right); | |
} | |
public static Percent operator -(Percent percentage) | |
{ | |
return -(percentage._value); | |
} | |
public static Percent operator +(Percent left, Percent right) | |
{ | |
return new Percent(left._value + right._value); | |
} | |
public static Percent operator -(Percent left, Percent right) | |
{ | |
return new Percent(left._value - right._value); | |
} | |
public static Percent operator *(Percent left, Percent right) | |
{ | |
return new Percent(left._value * right._value); | |
} | |
public static Percent operator *(decimal left, Percent right) | |
{ | |
return new Percent(left * right._value); | |
} | |
public static Percent operator *(Percent left, decimal right) | |
{ | |
return new Percent(left._value * right); | |
} | |
public override string ToString() | |
{ | |
return string.Format("{0:P2}", Math.Round(_value, 2, MidpointRounding.AwayFromZero)); | |
} | |
public string ToString(string format) | |
{ | |
return _value.ToString(format); | |
} | |
public string ToString(IFormatProvider formatProvider) | |
{ | |
return _value.ToString(formatProvider); | |
} | |
public string ToString(string format, IFormatProvider formatProvider) | |
{ | |
return _value.ToString(format, formatProvider); | |
} | |
#region ISerializable | |
/// <summary> | |
/// Deserialization constructor | |
/// </summary> | |
/// <param name="info"></param> | |
/// <param name="context"></param> | |
public Percent(SerializationInfo info, StreamingContext context) | |
{ | |
_value = info.GetDecimal("percentage"); | |
} | |
/// <summary> | |
/// Serialization method | |
/// </summary> | |
/// <param name="info"></param> | |
/// <param name="context"></param> | |
public void GetObjectData(SerializationInfo info, StreamingContext context) | |
{ | |
info.AddValue("percentage", _value); | |
} | |
#endregion | |
#region IConvertible | |
public TypeCode GetTypeCode() | |
{ | |
return TypeCode.Decimal; | |
} | |
public bool ToBoolean(IFormatProvider provider) | |
{ | |
return Convert.ToBoolean(_value, provider); | |
} | |
public byte ToByte(IFormatProvider provider) | |
{ | |
return Convert.ToByte(_value, provider); | |
} | |
public char ToChar(IFormatProvider provider) | |
{ | |
return Convert.ToChar(_value, provider); | |
} | |
public DateTime ToDateTime(IFormatProvider provider) | |
{ | |
return Convert.ToDateTime(_value, provider); | |
} | |
public decimal ToDecimal(IFormatProvider provider) | |
{ | |
return Convert.ToDecimal(_value, provider); | |
} | |
public double ToDouble(IFormatProvider provider) | |
{ | |
return Convert.ToDouble(_value, provider); | |
} | |
public short ToInt16(IFormatProvider provider) | |
{ | |
return Convert.ToInt16(_value, provider); | |
} | |
public int ToInt32(IFormatProvider provider) | |
{ | |
return Convert.ToInt32(_value, provider); | |
} | |
public long ToInt64(IFormatProvider provider) | |
{ | |
return Convert.ToInt64(_value, provider); | |
} | |
public sbyte ToSByte(IFormatProvider provider) | |
{ | |
return Convert.ToSByte(_value, provider); | |
} | |
public float ToSingle(IFormatProvider provider) | |
{ | |
return Convert.ToSingle(_value, provider); | |
} | |
public object ToType(Type conversionType, IFormatProvider provider) | |
{ | |
return Convert.ChangeType(_value, conversionType, provider); | |
} | |
public ushort ToUInt16(IFormatProvider provider) | |
{ | |
return Convert.ToUInt16(_value, provider); | |
} | |
public uint ToUInt32(IFormatProvider provider) | |
{ | |
return Convert.ToUInt32(_value, provider); | |
} | |
public ulong ToUInt64(IFormatProvider provider) | |
{ | |
return Convert.ToUInt64(_value, provider); | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace CN.Lib.Types | |
{ | |
public static class PercentExtensions | |
{ | |
public static Percent Sum(this IEnumerable<Percent> percentages) | |
{ | |
var sum = new Percent(0m); | |
return percentages.Aggregate(sum, (current, percentage) => current + percentage); | |
} | |
public static Percent Sum<T>(this IEnumerable<T> amounts, Func<T, Percent> func) | |
{ | |
return amounts.Select(func).Sum(); | |
} | |
public static Percent Sum(this IEnumerable<Percent> amounts, Func<Percent, bool> func) | |
{ | |
return amounts.Where(func).Sum(); | |
} | |
public static Percent Average(this IEnumerable<Percent> percentages) | |
{ | |
return percentages.Select(v => (decimal) v).Average(); | |
} | |
public static Percent Abs(this Percent percentage) | |
{ | |
return Math.Abs((decimal) percentage); | |
} | |
public static Percent Round(this Percent percentage) | |
{ | |
return Math.Round((decimal)percentage, 4); | |
} | |
public static Percent Round(this Percent percentage, int decimals) | |
{ | |
return Math.Round((decimal)percentage, decimals); | |
} | |
public static Percent Round(this Percent percentage, MidpointRounding rounding) | |
{ | |
return Math.Round((decimal)percentage, rounding); | |
} | |
public static Percent Round(this Percent percentage, int decimals, MidpointRounding rounding) | |
{ | |
return Math.Round((decimal)percentage, decimals, rounding); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace CN.Lib.Types | |
{ | |
public static class SiPrefix | |
{ | |
public static decimal Yocto | |
{ | |
get { return 0.000000000000000000000001m; } | |
} | |
public static decimal Zepto | |
{ | |
get { return 0.000000000000000000001m; } | |
} | |
public static decimal Atto | |
{ | |
get { return 0.000000000000000001m; } | |
} | |
public static decimal Femto | |
{ | |
get { return 0.000000000000001m; } | |
} | |
public static decimal Pico | |
{ | |
get { return 0.000000000001m; } | |
} | |
public static decimal Nano | |
{ | |
get { return 0.000000001m; } | |
} | |
/// <summary> | |
/// Millionth | |
/// </summary> | |
public static decimal Micro | |
{ | |
get { return 0.000001m; } | |
} | |
/// <summary> | |
/// Thousandth | |
/// </summary> | |
public static decimal Milli | |
{ | |
get { return 0.001m; } | |
} | |
/// <summary> | |
/// Hundredth | |
/// </summary> | |
public static decimal Centi | |
{ | |
get { return 0.01m; } | |
} | |
/// <summary> | |
/// Tenth | |
/// </summary> | |
public static decimal Deci | |
{ | |
get { return 0.1m; } | |
} | |
/// <summary> | |
/// One | |
/// </summary> | |
public static decimal One | |
{ | |
get { return decimal.One; } | |
} | |
public static decimal Yotta | |
{ | |
get { return 1000000000000000000000000m; } | |
} | |
public static decimal Zetta | |
{ | |
get { return 1000000000000000000000m; } | |
} | |
public static decimal Exa | |
{ | |
get { return 1000000000000000000m; } | |
} | |
public static decimal Peta | |
{ | |
get { return 1000000000000000m; } | |
} | |
public static decimal Tera | |
{ | |
get { return 1000000000000m; } | |
} | |
public static decimal Giga | |
{ | |
get { return 1000000000m; } | |
} | |
/// <summary> | |
/// Million | |
/// </summary> | |
public static decimal Mega | |
{ | |
get { return 1000000m; } | |
} | |
/// <summary> | |
/// Thousand | |
/// </summary> | |
public static decimal Kilo | |
{ | |
get { return 1000m; } | |
} | |
/// <summary> | |
/// Hundred | |
/// </summary> | |
public static decimal Hecto | |
{ | |
get { return 100m; } | |
} | |
/// <summary> | |
/// Ten | |
/// </summary> | |
public static decimal Deca | |
{ | |
get { return 10m; } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment