在C#中将double转换为fraction作为字符串

我想在C#中显示double值作为分数,我该怎么做?

谢谢

试试这个C#的Fraction类。

/* * Author: Syed Mehroz Alam * Email: smehrozalam@yahoo.com * URL: Programming Home "http://www.geocities.com/smehrozalam/" * Date: 6/15/2004 * Time: 10:54 AM * */ using System; namespace Mehroz { ///  /// Classes Contained: /// Fraction /// FractionException ///  /// Class name: Fraction /// Developed by: Syed Mehroz Alam /// Email: smehrozalam@yahoo.com /// URL: Programming Home "http://www.geocities.com/smehrozalam/" /// Version: 2.0 /// /// What's new in version 2.0: /// * Changed Numerator and Denominator from Int32(integer) to Int64(long) for increased range /// * renamed ConvertToString() to (overloaded) ToString() /// * added the capability of detecting/raising overflow exceptions /// * Fixed the bug that very small numbers eg 0.00000001 could not be converted to fraction /// * Other minor bugs fixed /// /// What's new in version 2.1 /// * overloaded user-defined conversions to/from Fractions /// /// /// Properties: /// Numerator: Set/Get value for Numerator /// Denominator: Set/Get value for Numerator /// Value: Set an integer value for the fraction /// /// Constructors: /// no arguments: initializes fraction as 0/1 /// (Numerator, Denominator): initializes fraction with the given numerator and denominator values /// (integer): initializes fraction with the given integer value /// (long): initializes fraction with the given long value /// (double): initializes fraction with the given double value /// (string): initializes fraction with the given string value /// the string can be an in the form of and integer, double or fraction. /// eg it can be like "123" or "123.321" or "123/456" /// /// Public Methods (Description is given with respective methods' definitions) /// (override) string ToString(Fraction) /// Fraction ToFraction(string) /// Fraction ToFraction(double) /// double ToDouble(Fraction) /// Fraction Duplicate() /// Fraction Inverse(integer) /// Fraction Inverse(Fraction) /// ReduceFraction(Fraction) /// Equals(object) /// GetHashCode() /// /// Private Methods (Description is given with respective methods' definitions) /// Initialize(Numerator, Denominator) /// Fraction Negate(Fraction) /// Fraction Add(Fraction1, Fraction2) /// /// Overloaded Operators (overloaded for Fractions, Integers and Doubles) /// Unary: - /// Binary: +,-,*,/ /// Relational and Logical Operators: ==,!=,<,>,<=,>= /// /// Overloaded user-defined conversions /// Implicit: From double/long/string to Fraction /// Explicit: From Fraction to double/string ///  public class Fraction { ///  /// Class attributes/members ///  long m_iNumerator; long m_iDenominator; ///  /// Constructors ///  public Fraction() { Initialize(0,1); } public Fraction(long iWholeNumber) { Initialize(iWholeNumber, 1); } public Fraction(double dDecimalValue) { Fraction temp=ToFraction(dDecimalValue); Initialize(temp.Numerator, temp.Denominator); } public Fraction(string strValue) { Fraction temp=ToFraction(strValue); Initialize(temp.Numerator, temp.Denominator); } public Fraction(long iNumerator, long iDenominator) { Initialize(iNumerator, iDenominator); } ///  /// Internal function for constructors ///  private void Initialize(long iNumerator, long iDenominator) { Numerator=iNumerator; Denominator=iDenominator; ReduceFraction(this); } ///  /// Properites ///  public long Denominator { get { return m_iDenominator; } set { if (value!=0) m_iDenominator=value; else throw new FractionException("Denominator cannot be assigned a ZERO Value"); } } public long Numerator { get { return m_iNumerator; } set { m_iNumerator=value; } } public long Value { set { m_iNumerator=value; m_iDenominator=1; } } ///  /// The function returns the current Fraction object as double ///  public double ToDouble() { return ( (double)this.Numerator/this.Denominator ); } ///  /// The function returns the current Fraction object as a string ///  public override string ToString() { string str; if ( this.Denominator==1 ) str=this.Numerator.ToString(); else str=this.Numerator + "/" + this.Denominator; return str; } ///  /// The function takes an string as an argument and returns its corresponding reduced fraction /// the string can be an in the form of and integer, double or fraction. /// eg it can be like "123" or "123.321" or "123/456" ///  public static Fraction ToFraction(string strValue) { int i; for (i=0;i /// The function takes a floating point number as an argument /// and returns its corresponding reduced fraction ///  public static Fraction ToFraction(double dValue) { try { checked { Fraction frac; if (dValue%1==0) // if whole number { frac=new Fraction( (long) dValue ); } else { double dTemp=dValue; long iMultiple=1; string strTemp=dValue.ToString(); while ( strTemp.IndexOf("E")>0 ) // if in the form like 12E-9 { dTemp*=10; iMultiple*=10; strTemp=dTemp.ToString(); } int i=0; while ( strTemp[i]!='.' ) i++; int iDigitsAfterDecimal=strTemp.Length-i-1; while ( iDigitsAfterDecimal>0 ) { dTemp*=10; iMultiple*=10; iDigitsAfterDecimal--; } frac=new Fraction( (int)Math.Round(dTemp) , iMultiple ); } return frac; } } catch(OverflowException) { throw new FractionException("Conversion not possible due to overflow"); } catch(Exception) { throw new FractionException("Conversion not possible"); } } ///  /// The function replicates current Fraction object ///  public Fraction Duplicate() { Fraction frac=new Fraction(); frac.Numerator=Numerator; frac.Denominator=Denominator; return frac; } ///  /// The function returns the inverse of a Fraction object ///  public static Fraction Inverse(Fraction frac1) { if (frac1.Numerator==0) throw new FractionException("Operation not possible (Denominator cannot be assigned a ZERO Value)"); long iNumerator=frac1.Denominator; long iDenominator=frac1.Numerator; return ( new Fraction(iNumerator, iDenominator)); } ///  /// Operators for the Fraction object /// includes -(unary), and binary opertors such as +,-,*,/ /// also includes relational and logical operators such as ==,!=,<,>,<=,>= ///  public static Fraction operator -(Fraction frac1) { return ( Negate(frac1) ); } public static Fraction operator +(Fraction frac1, Fraction frac2) { return ( Add(frac1 , frac2) ); } public static Fraction operator +(int iNo, Fraction frac1) { return ( Add(frac1 , new Fraction(iNo) ) ); } public static Fraction operator +(Fraction frac1, int iNo) { return ( Add(frac1 , new Fraction(iNo) ) ); } public static Fraction operator +(double dbl, Fraction frac1) { return ( Add(frac1 , Fraction.ToFraction(dbl) ) ); } public static Fraction operator +(Fraction frac1, double dbl) { return ( Add(frac1 , Fraction.ToFraction(dbl) ) ); } public static Fraction operator -(Fraction frac1, Fraction frac2) { return ( Add(frac1 , -frac2) ); } public static Fraction operator -(int iNo, Fraction frac1) { return ( Add(-frac1 , new Fraction(iNo) ) ); } public static Fraction operator -(Fraction frac1, int iNo) { return ( Add(frac1 , -(new Fraction(iNo)) ) ); } public static Fraction operator -(double dbl, Fraction frac1) { return ( Add(-frac1 , Fraction.ToFraction(dbl) ) ); } public static Fraction operator -(Fraction frac1, double dbl) { return ( Add(frac1 , -Fraction.ToFraction(dbl) ) ); } public static Fraction operator *(Fraction frac1, Fraction frac2) { return ( Multiply(frac1 , frac2) ); } public static Fraction operator *(int iNo, Fraction frac1) { return ( Multiply(frac1 , new Fraction(iNo) ) ); } public static Fraction operator *(Fraction frac1, int iNo) { return ( Multiply(frac1 , new Fraction(iNo) ) ); } public static Fraction operator *(double dbl, Fraction frac1) { return ( Multiply(frac1 , Fraction.ToFraction(dbl) ) ); } public static Fraction operator *(Fraction frac1, double dbl) { return ( Multiply(frac1 , Fraction.ToFraction(dbl) ) ); } public static Fraction operator /(Fraction frac1, Fraction frac2) { return ( Multiply( frac1 , Inverse(frac2) ) ); } public static Fraction operator /(int iNo, Fraction frac1) { return ( Multiply( Inverse(frac1) , new Fraction(iNo) ) ); } public static Fraction operator /(Fraction frac1, int iNo) { return ( Multiply( frac1 , Inverse(new Fraction(iNo)) ) ); } public static Fraction operator /(double dbl, Fraction frac1) { return ( Multiply( Inverse(frac1) , Fraction.ToFraction(dbl) ) ); } public static Fraction operator /(Fraction frac1, double dbl) { return ( Multiply( frac1 , Fraction.Inverse( Fraction.ToFraction(dbl) ) ) ); } public static bool operator ==(Fraction frac1, Fraction frac2) { return frac1.Equals(frac2); } public static bool operator !=(Fraction frac1, Fraction frac2) { return ( !frac1.Equals(frac2) ); } public static bool operator ==(Fraction frac1, int iNo) { return frac1.Equals( new Fraction(iNo)); } public static bool operator !=(Fraction frac1, int iNo) { return ( !frac1.Equals( new Fraction(iNo)) ); } public static bool operator ==(Fraction frac1, double dbl) { return frac1.Equals( new Fraction(dbl)); } public static bool operator !=(Fraction frac1, double dbl) { return ( !frac1.Equals( new Fraction(dbl)) ); } public static bool operator<(Fraction frac1, Fraction frac2) { return frac1.Numerator * frac2.Denominator < frac2.Numerator * frac1.Denominator; } public static bool operator>(Fraction frac1, Fraction frac2) { return frac1.Numerator * frac2.Denominator > frac2.Numerator * frac1.Denominator; } public static bool operator<=(Fraction frac1, Fraction frac2) { return frac1.Numerator * frac2.Denominator <= frac2.Numerator * frac1.Denominator; } public static bool operator>=(Fraction frac1, Fraction frac2) { return frac1.Numerator * frac2.Denominator >= frac2.Numerator * frac1.Denominator; } ///  /// overloaed user defined conversions: from numeric data types to Fractions ///  public static implicit operator Fraction(long lNo) { return new Fraction(lNo); } public static implicit operator Fraction(double dNo) { return new Fraction(dNo); } public static implicit operator Fraction(string strNo) { return new Fraction(strNo); } ///  /// overloaed user defined conversions: from fractions to double and string ///  public static explicit operator double(Fraction frac) { return frac.ToDouble(); } public static implicit operator string(Fraction frac) { return frac.ToString(); } ///  /// checks whether two fractions are equal ///  public override bool Equals(object obj) { Fraction frac=(Fraction)obj; return ( Numerator==frac.Numerator && Denominator==frac.Denominator); } ///  /// returns a hash code for this fraction ///  public override int GetHashCode() { return ( Convert.ToInt32((Numerator ^ Denominator) & 0xFFFFFFFF) ) ; } ///  /// internal function for negation ///  private static Fraction Negate(Fraction frac1) { long iNumerator=-frac1.Numerator; long iDenominator=frac1.Denominator; return ( new Fraction(iNumerator, iDenominator) ); } ///  /// internal functions for binary operations ///  private static Fraction Add(Fraction frac1, Fraction frac2) { try { checked { long iNumerator=frac1.Numerator*frac2.Denominator + frac2.Numerator*frac1.Denominator; long iDenominator=frac1.Denominator*frac2.Denominator; return ( new Fraction(iNumerator, iDenominator) ); } } catch(OverflowException) { throw new FractionException("Overflow occurred while performing arithemetic operation"); } catch(Exception) { throw new FractionException("An error occurred while performing arithemetic operation"); } } private static Fraction Multiply(Fraction frac1, Fraction frac2) { try { checked { long iNumerator=frac1.Numerator*frac2.Numerator; long iDenominator=frac1.Denominator*frac2.Denominator; return ( new Fraction(iNumerator, iDenominator) ); } } catch(OverflowException) { throw new FractionException("Overflow occurred while performing arithemetic operation"); } catch(Exception) { throw new FractionException("An error occurred while performing arithemetic operation"); } } ///  /// The function returns GCD of two numbers (used for reducing a Fraction) ///  private static long GCD(long iNo1, long iNo2) { // take absolute values if (iNo1 < 0) iNo1 = -iNo1; if (iNo2 < 0) iNo2 = -iNo2; do { if (iNo1 < iNo2) { long tmp = iNo1; // swap the two operands iNo1 = iNo2; iNo2 = tmp; } iNo1 = iNo1 % iNo2; } while (iNo1 != 0); return iNo2; } ///  /// The function reduces(simplifies) a Fraction object by dividing both its numerator /// and denominator by their GCD ///  public static void ReduceFraction(Fraction frac) { try { if (frac.Numerator==0) { frac.Denominator=1; return; } long iGCD=GCD(frac.Numerator, frac.Denominator); frac.Numerator/=iGCD; frac.Denominator/=iGCD; if ( frac.Denominator<0 ) // if -ve sign in denominator { //pass -ve sign to numerator frac.Numerator*=-1; frac.Denominator*=-1; } } // end try catch(Exception exp) { throw new FractionException("Cannot reduce Fraction: " + exp.Message); } } } //end class Fraction ///  /// Exception class for Fraction, derived from System.Exception ///  public class FractionException : Exception { public FractionException() : base() {} public FractionException(string Message) : base(Message) {} public FractionException(string Message, Exception InnerException) : base(Message, InnerException) {} } //end class FractionException } //end namespace Mehroz 

正如@Tillito在评论中指出的那样,我仔细检查了以下代码:

 using System.IO; using System; using Mehroz; class Program { static void Main() { double d = .5; string str = new Fraction(d).ToString(); Console.WriteLine(str); } } 

哪个输出:

1/2

将随后的代码放入静态类中以创建扩展,然后使用如下:

 var number = 2.83; var result = number.ToFractions(4); 

预期结果:“ 2 3/4

码:

 public static string ToFractions(this double number, int precision = 4) { int w, n, d; RoundToMixedFraction(number, precision, out w, out n, out d); var ret = $"{w}"; if (w > 0) { if (n > 0) ret = $"{w} {n}/{d}"; } else { if (n > 0) ret = $"{n}/{d}"; } return ret; } static void RoundToMixedFraction(double input, int accuracy, out int whole, out int numerator, out int denominator) { double dblAccuracy = (double)accuracy; whole = (int)(Math.Truncate(input)); var fraction = Math.Abs(input - whole); if (fraction == 0) { numerator = 0; denominator = 1; return; } var n = Enumerable.Range(0, accuracy + 1).SkipWhile(e => (e / dblAccuracy) < fraction).First(); var hi = n / dblAccuracy; var lo = (n - 1) / dblAccuracy; if ((fraction - lo) < (hi - fraction)) n--; if (n == accuracy) { whole++; numerator = 0; denominator = 1; return; } var gcd = GCD(n, accuracy); numerator = n / gcd; denominator = accuracy / gcd; } static int GCD(int a, int b) { if (b == 0) return a; else return GCD(b, a % b); } 
Interesting Posts