मान लें कि हमारे पास 0.33 है, हमें "1/3" आउटपुट की आवश्यकता है। यदि हमारे पास "0.4" है, तो हमें "2/5" आउटपुट की आवश्यकता है।
यह सामान्य मामले में गलत है, क्योंकि 1/3 = 0.3333333 = 0. (3) इसके अलावा, ऊपर दिए गए समाधानों में से यह पता लगाना असंभव है कि दशमलव को परिभाषित परिशुद्धता के साथ अंश में परिवर्तित किया जा सकता है, क्योंकि आउटपुट हमेशा भिन्न होता है।
लेकिन, मैं अनंत ज्यामितीय श्रृंखला के विचार पर आधारित कई विकल्पों के साथ अपने व्यापक कार्य का सुझाव देता हूं , विशेष रूप से सूत्र पर:
सबसे पहले यह फ़ंक्शन स्ट्रिंग प्रतिनिधित्व में अंश की अवधि खोजने की कोशिश कर रहा है। उसके बाद ऊपर वर्णित फॉर्मूला लागू किया जाता है।
तर्कसंगत संख्या कोड को स्टीफन एम। मैककेमी तर्कसंगत संख्या कार्यान्वयन से C # में उधार लिया गया है। मुझे उम्मीद है कि अन्य भाषाओं पर अपने कोड को पोर्ट करने के लिए बहुत मुश्किल नहीं है।
/// <summary>
/// Convert decimal to fraction
/// </summary>
/// <param name="value">decimal value to convert</param>
/// <param name="result">result fraction if conversation is succsess</param>
/// <param name="decimalPlaces">precision of considereation frac part of value</param>
/// <param name="trimZeroes">trim zeroes on the right part of the value or not</param>
/// <param name="minPeriodRepeat">minimum period repeating</param>
/// <param name="digitsForReal">precision for determination value to real if period has not been founded</param>
/// <returns></returns>
public static bool FromDecimal(decimal value, out Rational<T> result,
int decimalPlaces = 28, bool trimZeroes = false, decimal minPeriodRepeat = 2, int digitsForReal = 9)
{
var valueStr = value.ToString("0.0000000000000000000000000000", CultureInfo.InvariantCulture);
var strs = valueStr.Split('.');
long intPart = long.Parse(strs[0]);
string fracPartTrimEnd = strs[1].TrimEnd(new char[] { '0' });
string fracPart;
if (trimZeroes)
{
fracPart = fracPartTrimEnd;
decimalPlaces = Math.Min(decimalPlaces, fracPart.Length);
}
else
fracPart = strs[1];
result = new Rational<T>();
try
{
string periodPart;
bool periodFound = false;
int i;
for (i = 0; i < fracPart.Length; i++)
{
if (fracPart[i] == '0' && i != 0)
continue;
for (int j = i + 1; j < fracPart.Length; j++)
{
periodPart = fracPart.Substring(i, j - i);
periodFound = true;
decimal periodRepeat = 1;
decimal periodStep = 1.0m / periodPart.Length;
var upperBound = Math.Min(fracPart.Length, decimalPlaces);
int k;
for (k = i + periodPart.Length; k < upperBound; k += 1)
{
if (periodPart[(k - i) % periodPart.Length] != fracPart[k])
{
periodFound = false;
break;
}
periodRepeat += periodStep;
}
if (!periodFound && upperBound - k <= periodPart.Length && periodPart[(upperBound - i) % periodPart.Length] > '5')
{
var ind = (k - i) % periodPart.Length;
var regroupedPeriod = (periodPart.Substring(ind) + periodPart.Remove(ind)).Substring(0, upperBound - k);
ulong periodTailPlusOne = ulong.Parse(regroupedPeriod) + 1;
ulong fracTail = ulong.Parse(fracPart.Substring(k, regroupedPeriod.Length));
if (periodTailPlusOne == fracTail)
periodFound = true;
}
if (periodFound && periodRepeat >= minPeriodRepeat)
{
result = FromDecimal(strs[0], fracPart.Substring(0, i), periodPart);
break;
}
else
periodFound = false;
}
if (periodFound)
break;
}
if (!periodFound)
{
if (fracPartTrimEnd.Length >= digitsForReal)
return false;
else
{
result = new Rational<T>(long.Parse(strs[0]), 1, false);
if (fracPartTrimEnd.Length != 0)
result = new Rational<T>(ulong.Parse(fracPartTrimEnd), TenInPower(fracPartTrimEnd.Length));
return true;
}
}
return true;
}
catch
{
return false;
}
}
public static Rational<T> FromDecimal(string intPart, string fracPart, string periodPart)
{
Rational<T> firstFracPart;
if (fracPart != null && fracPart.Length != 0)
{
ulong denominator = TenInPower(fracPart.Length);
firstFracPart = new Rational<T>(ulong.Parse(fracPart), denominator);
}
else
firstFracPart = new Rational<T>(0, 1, false);
Rational<T> secondFracPart;
if (periodPart != null && periodPart.Length != 0)
secondFracPart =
new Rational<T>(ulong.Parse(periodPart), TenInPower(fracPart.Length)) *
new Rational<T>(1, Nines((ulong)periodPart.Length), false);
else
secondFracPart = new Rational<T>(0, 1, false);
var result = firstFracPart + secondFracPart;
if (intPart != null && intPart.Length != 0)
{
long intPartLong = long.Parse(intPart);
result = new Rational<T>(intPartLong, 1, false) + (intPartLong == 0 ? 1 : Math.Sign(intPartLong)) * result;
}
return result;
}
private static ulong TenInPower(int power)
{
ulong result = 1;
for (int l = 0; l < power; l++)
result *= 10;
return result;
}
private static decimal TenInNegPower(int power)
{
decimal result = 1;
for (int l = 0; l > power; l--)
result /= 10.0m;
return result;
}
private static ulong Nines(ulong power)
{
ulong result = 9;
if (power >= 0)
for (ulong l = 0; l < power - 1; l++)
result = result * 10 + 9;
return result;
}
Usings के कुछ उदाहरण हैं:
Rational<long>.FromDecimal(0.33333333m, out r, 8, false);
// then r == 1 / 3;
Rational<long>.FromDecimal(0.33333333m, out r, 9, false);
// then r == 33333333 / 100000000;
दाहिने भाग के साथ आपका मामला शून्य भाग ट्रिमिंग:
Rational<long>.FromDecimal(0.33m, out r, 28, true);
// then r == 1 / 3;
Rational<long>.FromDecimal(0.33m, out r, 28, true);
// then r == 33 / 100;
न्यूनतम अवधि डेमोस्ट्रेशन:
Rational<long>.FromDecimal(0.123412m, out r, 28, true, 1.5m));
// then r == 1234 / 9999;
Rational<long>.FromDecimal(0.123412m, out r, 28, true, 1.6m));
// then r == 123412 / 1000000; because of minimu repeating of period is 0.1234123 in this case.
अंत में गोलाई:
Rational<long>.FromDecimal(0.8888888888888888888888888889m, out r));
// then r == 8 == 9;
सबसे दिलचस्प मामला:
Rational<long>.FromDecimal(0.12345678m, out r, 28, true, 2, 9);
// then r == 12345678 / 100000000;
Rational<long>.FromDecimal(0.12345678m, out r, 28, true, 2, 8);
// Conversation failed, because of period has not been founded and there are too many digits in fraction part of input value.
Rational<long>.FromDecimal(0.12121212121212121m, out r, 28, true, 2, 9));
// then r == 4 / 33; Despite of too many digits in input value, period has been founded. Thus it's possible to convert value to fraction.
अन्य परीक्षण और कोड हर कोई मेरे मैथफंक्शन लायब्रेरी में जीथब पर पा सकता है ।
.33
=>"1/3"
उदाहरण चिंताओं मुझे; मैं उम्मीद होती है.33
=>"33/100"
। मेरा मानना है कि आप.33...
निश्चित रूप से मतलब है, लेकिन यह सवाल के साथ एक समस्या को उजागर करता है - इससे पहले कि हम एक एल्गोरिथ्म पर व्यवस्थित हो सकें हमें अपेक्षित व्यवहार पर निर्णय लेने की आवश्यकता है। @ देबिल्स्की के पाइथन उत्तर का उपयोग करता है.limit_denominator()
जो 10 ^ 7 के अधिकतम हर के लिए चूक करता है ; शायद अभ्यास में एक अच्छा डिफ़ॉल्ट, लेकिन यह अभी भी बग प्रस्तुत कर सकते हैं अगर आप सावधान नहीं हैं, और करता है वापसी"33/100"
में.33
मामला।