提供了各种运算符并实现了IComparable接口,可以像使用系统自带数据类型一样方便地使用分数.
提供将字符串转化为分数以及将分数转化为小数的方法.
PS:求小数转化为分数的算法~~~
//Version 0.9.7
using System;
using IntType = System.Int64; //整形数和小数的类型可根据需要定义
using RealType = System.Double;
namespace Takamachi660.Math
{
public class FractionException : System.Exception
{
public FractionException(string msg) : base(msg) { }
public FractionException() : base() { }
}
[Serializable]
public struct Fraction : IComparable<Fraction>, IComparable
{
private IntType iNum, iDen; //分子/分母,私有字段
public IntType iNumerator { get { return iNum; } } //外部通过只读属性获取分子和分母的值
public IntType iDenominator { get { return iDen; } }
public Fraction(Fraction value)
{
this.iNum = value.iNum;
this.iDen = value.iDen;
Simplify();
}
public Fraction(IntType iNum, IntType iDen)
{
this.iNum = iNum;
this.iDen = iDen;
Simplify();
}
public Fraction(string s)
{
if (string.IsNullOrEmpty(s))
{
this.iNum = 0;
this.iDen = 1;
}
else
{
this = ConvertFromString(s);
}
}
private void DenZeroCheck()
{
if (this.iDen == 0)
{
throw new FractionException("分母为\"0\"");
}
}
private Fraction Simplify()
{
DenZeroCheck();
if (iDen < 0)
{
iDen *= -1;
iNum *= -1;
}
IntType cm = CommonDivisor(Math.Abs(iNum), iDen);
if (cm == 1)
return this;
iNum /= cm;
iDen /= cm;
return this;
}
public override int GetHashCode()
{
Simplify();
return ((double)iNum / (double)iDen).GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is Fraction)
return iNum == ((Fraction)obj).iNum && iDen == ((Fraction)obj).iDen;
return false;
}
public override string ToString()
{
string strOutput;
Simplify();
if (iDen != 1)
strOutput = string.Format(@"{0}/{1}", iNum, iDen);
else
strOutput = string.Format(@"{0}", iNum);
return strOutput;
}
public RealType ToReal()
{
return (RealType)this.iNum / (RealType)this.iDen;
}
private static IntType CommonDivisor(IntType m, IntType n)
{
m = m < 0 ? -m : m;
n = n < 0 ? -n : n;
IntType temp;
if (n < m)
{
temp = n;
n = m;
m = temp;
}
while (m != 0)
{
temp = n % m;
n = m;
m = temp;
}
return n;
}
private static IntType CommonMultiple(IntType m, IntType n)
{
IntType p = Math.Abs(n * m);
n = CommonDivisor(m, n);
return p / n;
}
public void SetValue(IntType iNum, IntType iDen)
{
this.iNum = iNum;
this.iDen = iDen;
Simplify();
}
public void SetValue(string s)
{
this = ConvertFromString(s);
}
public static Fraction ConvertFromString(string s)
{
Fraction output;
if (!Fraction.TryParse(s, out output))
{
throw new FractionException(string.Format("无法将字符串\"{0}\"转化为分数", s));
}
return output;
}
public static bool TryParse(string s, out Fraction result) //将字符串转化为分数
{
s.Trim();
if (s.IndexOf(@"/") < 0)
{
result.iDen = 1;
if (!IntType.TryParse(s, out result.iNum))
{
result.iNum = 0;
return false;
}
return true;
}
if (s.IndexOf(@"/") != s.LastIndexOf(@"/"))
{
result.iNum = 0;
result.iDen = 1;
return false;
}
string[] temp = s.Split('/');
if (!IntType.TryParse(temp[0], out result.iNum) || !IntType.TryParse(temp[1], out result.iDen))
{
result.iNum = 0;
result.iDen = 1;
return false;
}
result.Simplify();
return true;
}
//重载比较运算符
public static bool operator ==(Fraction a, Fraction b)
{
return a.GetHashCode() == b.GetHashCode();
}
public static bool operator ==(IntType a, Fraction b)
{
//return new Fraction(a, 1) == b;
return a == b.ToReal();
}
public static bool operator ==(Fraction a, IntType b)
{
return b == a;
}
public static bool operator ==(RealType a, Fraction b)
{
return a == b.ToReal();
}
public static bool operator ==(Fraction a, RealType b)
{
return b == a;
}
public static bool operator !=(Fraction a, Fraction b)
{
return !(a == b);
}
public static bool operator !=(IntType a, Fraction b)
{
return !(a == b);
}
public static bool operator !=(Fraction a, IntType b)
{
return !(a == b);
}
public static bool operator !=(RealType a, Fraction b)
{
return !(a == b);
}
public static bool operator !=(Fraction a, RealType b)
{
return !(a == b);
}
public static bool operator >(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return false;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an > bn;
}
public static bool operator >(IntType a, Fraction b)
{
//return new Fraction(a, 1) > b;
return a > b.ToReal();
}
public static bool operator >(Fraction a, IntType b)
{
//return a > new Fraction(b, 1);
return a.ToReal() > b;
}
public static bool operator >(RealType a, Fraction b)
{
return a > b.ToReal();
}
public static bool operator >(Fraction a, RealType b)
{
return a.ToReal() > b;
}
public static bool operator <(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return false;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an < bn;
}
public static bool operator <(IntType a, Fraction b)
{
//return new Fraction(a, 1) < b;
return a < b.ToReal();
}
public static bool operator <(Fraction a, IntType b)
{
//return a < new Fraction(b, 1);
return a.ToReal() < b;
}
public static bool operator <(RealType a, Fraction b)
{
return a < b.ToReal();
}
public static bool operator <(Fraction a, RealType b)
{
return a.ToReal() < b;
}
public static bool operator >=(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return true;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an >= bn;
}
public static bool operator >=(IntType a, Fraction b)
{
//return new Fraction(a, 1) >= b;
return a >= b.ToReal();
}
public static bool operator >=(Fraction a, IntType b)
{
//return a >= new Fraction(b, 1);
return a.ToReal() >= b;
}
public static bool operator >=(RealType a, Fraction b)
{
return a >= b.ToReal();
}
public static bool operator >=(Fraction a, RealType b)
{
return a.ToReal() >= b;
}
public static bool operator <=(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return true;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an <= bn;
}
public static bool operator <=(IntType a, Fraction b)
{
//return new Fraction(a, 1) <= b;
return a <= b.ToReal();
}
public static bool operator <=(Fraction a, IntType b)
{
//return a <= new Fraction(b, 1);
return a.ToReal() <= b;
}
public static bool operator <=(RealType a, Fraction b)
{
return a <= b.ToReal();
}
public static bool operator <=(Fraction a, RealType b)
{
return a.ToReal() <= b;
}
//重载四则运算符
public static Fraction operator +(Fraction a, Fraction b)
{
a.DenZeroCheck();
b.DenZeroCheck();
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return new Fraction(an + bn, cm);
}
public static Fraction operator +(IntType a, Fraction b)
{
return (new Fraction(a, 1) + b);
}
public static Fraction operator +(Fraction a, IntType b)
{
return b + a;
}
public static Fraction operator -(Fraction obj)
{
obj.iNum *= -1;
return obj;
}
public static Fraction operator -(Fraction a, Fraction b)
{
return a + (-b);
}
public static Fraction operator -(IntType a, Fraction b)
{
return a + (-b);
}
public static Fraction operator -(Fraction a, IntType b)
{
return a + (-b);
}
public static Fraction operator *(Fraction a, Fraction b)
{
return new Fraction(a.iNum * b.iNum, a.iDen * b.iDen);
}
public static Fraction operator *(IntType a, Fraction b)
{
return new Fraction(a, 1) * b;
}
public static Fraction operator *(Fraction a, IntType b)
{
return b * a;
}
public static Fraction operator !(Fraction obj)//求倒数
{
if (obj == 0)
throw new FractionException("无法求\"0\"的倒数");
return new Fraction(obj.iDen, obj.iNum);//交换分子与分母
}
public static Fraction operator /(Fraction a, Fraction b)
{
if (b == 0)
throw new FractionException("\"0\"作为除数");
return a * !b;
}
public static Fraction operator /(IntType a, Fraction b)
{
if (b == 0)
throw new FractionException("\"0\"作为除数");
return a * !b;
}
public static Fraction operator /(Fraction a, IntType b)
{
if (b == 0)
throw new FractionException("\"0\"作为除数");
a.iDen *= b;
return a.Simplify();
}
public static Fraction operator |(Fraction a, Fraction b)//求最大公约数
{
return new Fraction(CommonDivisor(a.iNum, b.iNum), CommonMultiple(a.iDen, b.iDen));
}
public static Fraction operator &(Fraction a, Fraction b)//求最小公倍数
{
return new Fraction(CommonMultiple(a.iNum, b.iNum), CommonDivisor(a.iDen, b.iDen));
}
int IComparable<Fraction>.CompareTo(Fraction other)
{
Fraction dis = this - other;
return (int)(dis.iNum / dis.iDen);
}
int IComparable.CompareTo(object other)
{
if (other is IntType)
{
return (int)((this - (IntType)other).ToReal());
}
else if (other is Fraction)
{
return (this as IComparable<Fraction>).CompareTo((Fraction)other);
}
else if (other is RealType)
{
return (int)(this.ToReal() - (RealType)other);
}
else
return 0;
}
}
}
using System;
using IntType = System.Int64; //整形数和小数的类型可根据需要定义
using RealType = System.Double;
namespace Takamachi660.Math
{
public class FractionException : System.Exception
{
public FractionException(string msg) : base(msg) { }
public FractionException() : base() { }
}
[Serializable]
public struct Fraction : IComparable<Fraction>, IComparable
{
private IntType iNum, iDen; //分子/分母,私有字段
public IntType iNumerator { get { return iNum; } } //外部通过只读属性获取分子和分母的值
public IntType iDenominator { get { return iDen; } }
public Fraction(Fraction value)
{
this.iNum = value.iNum;
this.iDen = value.iDen;
Simplify();
}
public Fraction(IntType iNum, IntType iDen)
{
this.iNum = iNum;
this.iDen = iDen;
Simplify();
}
public Fraction(string s)
{
if (string.IsNullOrEmpty(s))
{
this.iNum = 0;
this.iDen = 1;
}
else
{
this = ConvertFromString(s);
}
}
private void DenZeroCheck()
{
if (this.iDen == 0)
{
throw new FractionException("分母为\"0\"");
}
}
private Fraction Simplify()
{
DenZeroCheck();
if (iDen < 0)
{
iDen *= -1;
iNum *= -1;
}
IntType cm = CommonDivisor(Math.Abs(iNum), iDen);
if (cm == 1)
return this;
iNum /= cm;
iDen /= cm;
return this;
}
public override int GetHashCode()
{
Simplify();
return ((double)iNum / (double)iDen).GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is Fraction)
return iNum == ((Fraction)obj).iNum && iDen == ((Fraction)obj).iDen;
return false;
}
public override string ToString()
{
string strOutput;
Simplify();
if (iDen != 1)
strOutput = string.Format(@"{0}/{1}", iNum, iDen);
else
strOutput = string.Format(@"{0}", iNum);
return strOutput;
}
public RealType ToReal()
{
return (RealType)this.iNum / (RealType)this.iDen;
}
private static IntType CommonDivisor(IntType m, IntType n)
{
m = m < 0 ? -m : m;
n = n < 0 ? -n : n;
IntType temp;
if (n < m)
{
temp = n;
n = m;
m = temp;
}
while (m != 0)
{
temp = n % m;
n = m;
m = temp;
}
return n;
}
private static IntType CommonMultiple(IntType m, IntType n)
{
IntType p = Math.Abs(n * m);
n = CommonDivisor(m, n);
return p / n;
}
public void SetValue(IntType iNum, IntType iDen)
{
this.iNum = iNum;
this.iDen = iDen;
Simplify();
}
public void SetValue(string s)
{
this = ConvertFromString(s);
}
public static Fraction ConvertFromString(string s)
{
Fraction output;
if (!Fraction.TryParse(s, out output))
{
throw new FractionException(string.Format("无法将字符串\"{0}\"转化为分数", s));
}
return output;
}
public static bool TryParse(string s, out Fraction result) //将字符串转化为分数
{
s.Trim();
if (s.IndexOf(@"/") < 0)
{
result.iDen = 1;
if (!IntType.TryParse(s, out result.iNum))
{
result.iNum = 0;
return false;
}
return true;
}
if (s.IndexOf(@"/") != s.LastIndexOf(@"/"))
{
result.iNum = 0;
result.iDen = 1;
return false;
}
string[] temp = s.Split('/');
if (!IntType.TryParse(temp[0], out result.iNum) || !IntType.TryParse(temp[1], out result.iDen))
{
result.iNum = 0;
result.iDen = 1;
return false;
}
result.Simplify();
return true;
}
//重载比较运算符
public static bool operator ==(Fraction a, Fraction b)
{
return a.GetHashCode() == b.GetHashCode();
}
public static bool operator ==(IntType a, Fraction b)
{
//return new Fraction(a, 1) == b;
return a == b.ToReal();
}
public static bool operator ==(Fraction a, IntType b)
{
return b == a;
}
public static bool operator ==(RealType a, Fraction b)
{
return a == b.ToReal();
}
public static bool operator ==(Fraction a, RealType b)
{
return b == a;
}
public static bool operator !=(Fraction a, Fraction b)
{
return !(a == b);
}
public static bool operator !=(IntType a, Fraction b)
{
return !(a == b);
}
public static bool operator !=(Fraction a, IntType b)
{
return !(a == b);
}
public static bool operator !=(RealType a, Fraction b)
{
return !(a == b);
}
public static bool operator !=(Fraction a, RealType b)
{
return !(a == b);
}
public static bool operator >(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return false;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an > bn;
}
public static bool operator >(IntType a, Fraction b)
{
//return new Fraction(a, 1) > b;
return a > b.ToReal();
}
public static bool operator >(Fraction a, IntType b)
{
//return a > new Fraction(b, 1);
return a.ToReal() > b;
}
public static bool operator >(RealType a, Fraction b)
{
return a > b.ToReal();
}
public static bool operator >(Fraction a, RealType b)
{
return a.ToReal() > b;
}
public static bool operator <(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return false;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an < bn;
}
public static bool operator <(IntType a, Fraction b)
{
//return new Fraction(a, 1) < b;
return a < b.ToReal();
}
public static bool operator <(Fraction a, IntType b)
{
//return a < new Fraction(b, 1);
return a.ToReal() < b;
}
public static bool operator <(RealType a, Fraction b)
{
return a < b.ToReal();
}
public static bool operator <(Fraction a, RealType b)
{
return a.ToReal() < b;
}
public static bool operator >=(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return true;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an >= bn;
}
public static bool operator >=(IntType a, Fraction b)
{
//return new Fraction(a, 1) >= b;
return a >= b.ToReal();
}
public static bool operator >=(Fraction a, IntType b)
{
//return a >= new Fraction(b, 1);
return a.ToReal() >= b;
}
public static bool operator >=(RealType a, Fraction b)
{
return a >= b.ToReal();
}
public static bool operator >=(Fraction a, RealType b)
{
return a.ToReal() >= b;
}
public static bool operator <=(Fraction a, Fraction b)
{
if (a.GetHashCode() == b.GetHashCode())
return true;
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return an <= bn;
}
public static bool operator <=(IntType a, Fraction b)
{
//return new Fraction(a, 1) <= b;
return a <= b.ToReal();
}
public static bool operator <=(Fraction a, IntType b)
{
//return a <= new Fraction(b, 1);
return a.ToReal() <= b;
}
public static bool operator <=(RealType a, Fraction b)
{
return a <= b.ToReal();
}
public static bool operator <=(Fraction a, RealType b)
{
return a.ToReal() <= b;
}
//重载四则运算符
public static Fraction operator +(Fraction a, Fraction b)
{
a.DenZeroCheck();
b.DenZeroCheck();
IntType cm = CommonMultiple(a.iDen, b.iDen);//分母的最小公倍数
IntType an = a.iNum * (cm / a.iDen);//a的分子
IntType bn = b.iNum * (cm / b.iDen);//b的分子
return new Fraction(an + bn, cm);
}
public static Fraction operator +(IntType a, Fraction b)
{
return (new Fraction(a, 1) + b);
}
public static Fraction operator +(Fraction a, IntType b)
{
return b + a;
}
public static Fraction operator -(Fraction obj)
{
obj.iNum *= -1;
return obj;
}
public static Fraction operator -(Fraction a, Fraction b)
{
return a + (-b);
}
public static Fraction operator -(IntType a, Fraction b)
{
return a + (-b);
}
public static Fraction operator -(Fraction a, IntType b)
{
return a + (-b);
}
public static Fraction operator *(Fraction a, Fraction b)
{
return new Fraction(a.iNum * b.iNum, a.iDen * b.iDen);
}
public static Fraction operator *(IntType a, Fraction b)
{
return new Fraction(a, 1) * b;
}
public static Fraction operator *(Fraction a, IntType b)
{
return b * a;
}
public static Fraction operator !(Fraction obj)//求倒数
{
if (obj == 0)
throw new FractionException("无法求\"0\"的倒数");
return new Fraction(obj.iDen, obj.iNum);//交换分子与分母
}
public static Fraction operator /(Fraction a, Fraction b)
{
if (b == 0)
throw new FractionException("\"0\"作为除数");
return a * !b;
}
public static Fraction operator /(IntType a, Fraction b)
{
if (b == 0)
throw new FractionException("\"0\"作为除数");
return a * !b;
}
public static Fraction operator /(Fraction a, IntType b)
{
if (b == 0)
throw new FractionException("\"0\"作为除数");
a.iDen *= b;
return a.Simplify();
}
public static Fraction operator |(Fraction a, Fraction b)//求最大公约数
{
return new Fraction(CommonDivisor(a.iNum, b.iNum), CommonMultiple(a.iDen, b.iDen));
}
public static Fraction operator &(Fraction a, Fraction b)//求最小公倍数
{
return new Fraction(CommonMultiple(a.iNum, b.iNum), CommonDivisor(a.iDen, b.iDen));
}
int IComparable<Fraction>.CompareTo(Fraction other)
{
Fraction dis = this - other;
return (int)(dis.iNum / dis.iDen);
}
int IComparable.CompareTo(object other)
{
if (other is IntType)
{
return (int)((this - (IntType)other).ToReal());
}
else if (other is Fraction)
{
return (this as IComparable<Fraction>).CompareTo((Fraction)other);
}
else if (other is RealType)
{
return (int)(this.ToReal() - (RealType)other);
}
else
return 0;
}
}
}