Beispiel #1
0
		public static FractionValue DoubleToFraction(double value)
		{
			// I used to always do "new FractionValue((decimal)value)" because
			// it does a good job for fixed length fractions.  But it made no attempt
			// to deal with repeating fractions, which are very common, so I've
			// pulled in the algorithm I used in my old RPN Calc 2.  Now I try both
			// algorithms and then see which appears to be better.
			FractionValue local = DoubleToRationalLocal(value);
			double localDouble = local.ToDouble();

			// Use FractionValue's algorithm.
			FractionValue fraction = new((decimal)value);
			double fractionDouble = fraction.ToDouble();

			// See how far both are off from the original value.
			double localEpsilon = Math.Abs(localDouble - value);
			double fractionEpsilon = Math.Abs(fractionDouble - value);

			// Use the number of digits too.  If I divide 5.0/7.0 and then
			// convert back to a fraction, then the local algorithm nails it.
			// But if I enter a value of "0.714285714285714", then local's
			// epsilon is a tad farther off, even though it comes up with a
			// much smaller and better denominator.
			int localDenomDigits = NumDigits(local.Denominator);
			int fracDenomDigits = NumDigits(fraction.Denominator);
			int diffDigits = Math.Abs(localDenomDigits - fracDenomDigits);

			FractionValue result;
			if (diffDigits <= 2)
			{
				// The denominator sizes are close, so choose the result based on which
				// epsilon is smaller.  This is important for "0.13333", which produces fewer
				// denominator digits with the local algorithm but a much larger epsilon.
				result = localEpsilon < fractionEpsilon ? local : fraction;
			}
			else
			{
				// The denominator sizes are several orders of magnitude different, so
				// choose the one with the fewest digits.  The FractionValue algorithm
				// can always get a small epsilon by using a huge denominator, but that
				// rarely produces a fraction the user actually wants.
				result = localDenomDigits < fracDenomDigits ? local : fraction;
			}

			return result;
		}