Created
July 3, 2019 18:41
-
-
Save rzubek/2f7b223344b5283e794df9435dc774be to your computer and use it in GitHub Desktop.
Very simple fixnum implementation for currency (dollars and cents)
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.Globalization; | |
namespace SomaSim.Util | |
{ | |
// | |
// very simple fixnum implementation that holds two digits after the decimal (so e.g. dollars and cents) | |
public struct Fixnum : IEquatable<Fixnum>, IComparable<Fixnum> | |
{ | |
public static readonly Fixnum ZERO = new Fixnum(); | |
public static readonly Fixnum MAX_VALUE = new Fixnum() { scaled = int.MaxValue }; | |
public static readonly Fixnum MIN_VALUE = new Fixnum() { scaled = int.MinValue }; | |
public const int SCALE = 100; // 2 digits = 10^2 = 100; | |
public int scaled; // raw representation without the decimal point | |
public Fixnum (int value) { scaled = value * SCALE; } | |
public Fixnum (float value) { scaled = (int)Math.Round(value * SCALE); } | |
public bool Equals (Fixnum other) => this.scaled == other.scaled; | |
public bool IsZero => this.scaled == ZERO.scaled; | |
public bool IsNotZero => this.scaled != ZERO.scaled; | |
public Fixnum Abs => (scaled >= 0) ? this : new Fixnum() { scaled = -scaled }; | |
public Fixnum Floor() => new Fixnum() { scaled = SCALE * (int)Math.Floor((double)scaled / SCALE) }; | |
public Fixnum Ceiling() => new Fixnum() { scaled = SCALE * (int)Math.Ceiling((double)scaled / SCALE) }; | |
public override bool Equals (object obj) => obj is Fixnum && this.scaled == ((Fixnum)obj).scaled; | |
public override int GetHashCode () => scaled.GetHashCode(); | |
public int CompareTo (Fixnum other) => this.scaled.CompareTo(other.scaled); | |
public static implicit operator Fixnum (int value) => new Fixnum(value); | |
public static explicit operator Fixnum (float value) => new Fixnum(value); | |
public static explicit operator int (Fixnum fixnum) => fixnum.scaled / SCALE; | |
public static explicit operator float (Fixnum fixnum) => fixnum.scaled / (float)SCALE; | |
public static bool operator == (Fixnum a, Fixnum b) => a.scaled == b.scaled; | |
public static bool operator != (Fixnum a, Fixnum b) => a.scaled != b.scaled; | |
public static bool operator < (Fixnum a, Fixnum b) => a.scaled < b.scaled; | |
public static bool operator > (Fixnum a, Fixnum b) => a.scaled > b.scaled; | |
public static bool operator <= (Fixnum a, Fixnum b) => a.scaled <= b.scaled; | |
public static bool operator >= (Fixnum a, Fixnum b) => a.scaled >= b.scaled; | |
public static Fixnum operator + (Fixnum f) => f; | |
public static Fixnum operator - (Fixnum f) => new Fixnum() { scaled = -f.scaled }; | |
public static Fixnum operator + (Fixnum a, Fixnum b) => new Fixnum() { scaled = a.scaled + b.scaled }; | |
public static Fixnum operator - (Fixnum a, Fixnum b) => new Fixnum() { scaled = a.scaled - b.scaled }; | |
public static Fixnum operator * (Fixnum a, Fixnum b) { | |
long result = ((long)a.scaled * b.scaled) / SCALE; | |
return new Fixnum() { scaled = (int)result }; | |
} | |
public static Fixnum operator / (Fixnum a, Fixnum b) { | |
long result = ((long)a.scaled * SCALE) / b.scaled; | |
return new Fixnum() { scaled = (int)result }; | |
} | |
public static Fixnum Clamp (Fixnum value, Fixnum min, Fixnum max) { | |
if (value < min) { return min; } | |
if (value > max) { return max; } | |
return value; | |
} | |
public static Fixnum Max (Fixnum a, Fixnum b) => (a.scaled > b.scaled) ? a : b; | |
public static Fixnum Min (Fixnum a, Fixnum b) => (a.scaled < b.scaled) ? a : b; | |
public override string ToString () => ((float)this).ToString(CultureInfo.InvariantCulture); | |
} | |
public sealed class FixnumEqualityComparer : IEqualityComparer<Fixnum> | |
{ | |
public bool Equals (Fixnum x, Fixnum y) { return x == y; } | |
public int GetHashCode (Fixnum obj) { return obj.GetHashCode(); } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment