using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace RainbowFraction { public struct RainbowFraction : IComparable, IComparable<RainbowFraction>, IEquatable<RainbowFraction> { #region 字段 private long _numerator; private long _denominator; #endregion #region 属性 /// <summary> /// 分子 /// </summary> public long Numerator { set {//分母分子不能同为负 if (value * _denominator >= 0) { _numerator = Math.Abs(value); _denominator = Math.Abs(_denominator); } else { _numerator = Math.Abs(value) * -1; _denominator = Math.Abs(_denominator); } } get { return _numerator; } } /// <summary> /// 分母 /// </summary> public long Denominator { get { return _denominator; } set {//分母分子不能同为负 if (value != 0) { if (_numerator * value >= 0) { _numerator = Math.Abs(_numerator); _denominator = Math.Abs(value); } else { _numerator = Math.Abs(_numerator) * -1; _denominator = Math.Abs(value); } } else { throw new RainbowFractionException("分母不可为0."); } } } /// <summary> /// 值 /// </summary> public double Value { get { return (double)Numerator / (double)Denominator; } } #endregion #region 构造 /// <summary> /// 以分子分母构造 /// </summary> /// <param name="srcNum"></param> /// <param name="srcDen"></param> public RainbowFraction(long srcNum, long srcDen) { if (srcDen == 0) { throw new RainbowFractionException("分母不可为0"); } if (srcNum * srcDen >= 0) { _numerator = Math.Abs(srcNum); _denominator = Math.Abs(srcDen); } else { _numerator = Math.Abs(srcNum) * -1; _denominator = Math.Abs(srcDen); } } /// <summary> /// 以double构造 /// </summary> /// <param name="srcDouble"></param> public RainbowFraction(double srcDouble) { _numerator = 0; _denominator = 1; RainbowFraction tmp = ToRainbowFraction(srcDouble); _numerator = tmp.Numerator; _denominator = tmp.Denominator; } /// <summary> /// 以字符串构造 /// </summary> /// <param name="srcString"></param> public RainbowFraction(string srcString) { _numerator = 0; _denominator = 1; RainbowFraction tmp = ToRainbowFraction(srcString); _numerator = tmp.Numerator; _denominator = tmp.Denominator; } #endregion #region 方法 /// <summary> /// double to fraction /// </summary> /// <param name="srcDouble"></param> /// <returns></returns> public static RainbowFraction ToRainbowFraction(double srcDouble) { RainbowFraction result = new RainbowFraction(); try { checked { string srcString = srcDouble.ToString(); double tmpNum = srcDouble; long tmpDen = 1; while (srcString.IndexOf(‘E‘) > 0) { tmpNum *= 10; tmpDen *= 10; srcString = tmpNum.ToString(); } if (srcString.Contains(‘.‘)) { int lengthAfterDot = srcString.Split(‘.‘)[1].Length; while (lengthAfterDot > 0) { tmpNum *= 10; tmpDen *= 10; lengthAfterDot--; } } result = new RainbowFraction((long)Math.Round(tmpNum), tmpDen); } } catch (OverflowException) { throw new RainbowFractionException("转换时发生溢出"); } catch (Exception) { throw new RainbowFractionException("转换失败"); } return result; } /// <summary> /// string to double /// </summary> /// <param name="srcString"></param> /// <returns></returns> public static RainbowFraction ToRainbowFraction(string srcString) { RainbowFraction result = new RainbowFraction(); try { double srcDouble = 0; Regex fracRegex = new Regex(@"^\d+\/\d+$"); if (double.TryParse(srcString, out srcDouble)) {//形如1.23 result = ToRainbowFraction(srcDouble); } else if (fracRegex.IsMatch(srcString)) {//形如1/23 result = new RainbowFraction(Convert.ToInt64(srcString.Split(‘/‘)[0]), Convert.ToInt64(srcString.Split(‘/‘)[1])); } else { throw new RainbowFractionException("输入字符串有误"); } } catch { throw new RainbowFractionException("转换失败"); } return result; } /// <summary> /// 转化为字符串 /// </summary> /// <returns></returns> public override string ToString() { return Denominator == 0 ? "NaN" : string.Format("{0}/{1}", Numerator, Denominator); } #endregion #region 接口实现 public int CompareTo(object obj) { int result = 0; double tmpValue = 0; if (obj is string) { if (this > ToRainbowFraction(obj as string)) { result = 1; } else if (this < ToRainbowFraction(obj as string)) { result = -1; } else { result = 0; } } else if (double.TryParse(obj as string, out tmpValue)) { result = this.Value.CompareTo(tmpValue); } else { throw new RainbowFractionException("比较失败"); } return result; } /// <summary> /// 分数比较 /// </summary> /// <param name="other"></param> /// <returns></returns> public int CompareTo(RainbowFraction other) { int result = 0; if (this > other) { result = 1; } else if (this < other) { result = -1; } return result; } /// <summary> /// 分数判等 /// </summary> /// <param name="other"></param> /// <returns></returns> public bool Equals(RainbowFraction other) { return this.Value == other.Value; } #endregion #region 隐式转化 /// <summary> /// double to fraction /// </summary> /// <param name="srcDouble"></param> /// <returns></returns> public static implicit operator RainbowFraction(double srcDouble) { RainbowFraction result = new RainbowFraction(srcDouble); return result; } /// <summary> /// fraction to double /// </summary> /// <param name="srcFrac"></param> /// <returns></returns> public static implicit operator double(RainbowFraction srcFrac) { return srcFrac.Value; } #endregion #region 运算符重载 //一元逻辑运算 public static RainbowFraction operator -(RainbowFraction srcFrac) { return new RainbowFraction(srcFrac.Numerator * -1, srcFrac.Denominator); } //二元逻辑运算 public static bool operator >(RainbowFraction left, RainbowFraction right) { return left.Value > right.Value; } public static bool operator >=(RainbowFraction left, RainbowFraction right) { return left.Value >= right.Value; } public static bool operator <(RainbowFraction left, RainbowFraction right) { return left.Value < right.Value; } public static bool operator <=(RainbowFraction left, RainbowFraction right) { return left.Value < right.Value; } public static bool operator ==(RainbowFraction left, RainbowFraction right) { return left.Value == right.Value; } public static bool operator !=(RainbowFraction left, RainbowFraction right) { return left.Value != right.Value; } //二元算术运算 public static RainbowFraction operator +(RainbowFraction left, RainbowFraction right) { RainbowFraction result = new RainbowFraction(); result.Denominator = left.Denominator * right.Denominator; result.Numerator = left.Numerator * right.Denominator + right.Numerator * left.Denominator; return result; } public static RainbowFraction operator -(RainbowFraction left, RainbowFraction right) { RainbowFraction result = new RainbowFraction(); result.Denominator = left.Denominator * right.Denominator; result.Numerator = left.Numerator * right.Denominator - right.Numerator * left.Denominator; return result; } public static RainbowFraction operator *(RainbowFraction left, RainbowFraction right) { RainbowFraction result = new RainbowFraction(); result.Denominator = left.Denominator * right.Denominator; result.Numerator = left.Numerator * right.Numerator; return result; } public static RainbowFraction operator /(RainbowFraction left, RainbowFraction right) { RainbowFraction result = new RainbowFraction(); result.Denominator = left.Denominator * right.Numerator; result.Numerator = left.Numerator * right.Denominator; return result; } #endregion } /// <summary> /// 分数异常 /// </summary> public class RainbowFractionException : Exception { public RainbowFractionException(string srcMsg) : base(srcMsg) { } } }