Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I recently had to perform this very task of working with a Decimal Data Type which is stored in our SQL Server database. At the Presentation Layer this value was edited as a fractional value in a TextBox. The complexity here was working with the Decimal Data Type which holds some pretty large values in comparison to int or long. So to reduce the opportunity for data overrun, I stuck with the Decimal Data Type throughout the conversion.</p> <p>Before I begin, I want to comment on Kirk's previous answer. He is absolutely correct as long as there are no assumptions made. However, if the developer only looks for repeating patterns within the confines of the Decimal Data Type .3333333... can be represented as 1/3. An example of the algorithm can be found at <a href="http://www.basic-mathematics.com/converting-repeating-decimals-to-fractions.html" rel="nofollow">basic-mathematics.com</a>. Again, this means you have to make assumptions based on the information available and using this method only captures a very small subset of repeating decimals. However for small numbers should be okay.</p> <p>Moving forward, let me give you a snapshot of my solution. If you want to read a complete example with additional code I created a <a href="http://www.jeffscorner.org/blog/post/C-Decimal-Data-Type-and-String-Fractions.aspx" rel="nofollow">blog post</a> with much more detail.</p> <p><strong>Convert Decimal Data Type to a String Fraction</strong></p> <pre><code>public static void DecimalToFraction(decimal value, ref decimal sign, ref decimal numerator, ref decimal denominator) { const decimal maxValue = decimal.MaxValue / 10.0M; // e.g. .25/1 = (.25 * 100)/(1 * 100) = 25/100 = 1/4 var tmpSign = value &lt; decimal.Zero ? -1 : 1; var tmpNumerator = Math.Abs(value); var tmpDenominator = decimal.One; // While numerator has a decimal value while ((tmpNumerator - Math.Truncate(tmpNumerator)) &gt; 0 &amp;&amp; tmpNumerator &lt; maxValue &amp;&amp; tmpDenominator &lt; maxValue) { tmpNumerator = tmpNumerator * 10; tmpDenominator = tmpDenominator * 10; } tmpNumerator = Math.Truncate(tmpNumerator); // Just in case maxValue boundary was reached. ReduceFraction(ref tmpNumerator, ref tmpDenominator); sign = tmpSign; numerator = tmpNumerator; denominator = tmpDenominator; } public static string DecimalToFraction(decimal value) { var sign = decimal.One; var numerator = decimal.One; var denominator = decimal.One; DecimalToFraction(value, ref sign, ref numerator, ref denominator); return string.Format("{0}/{1}", (sign * numerator).ToString().TruncateDecimal(), denominator.ToString().TruncateDecimal()); } </code></pre> <p>This is pretty straight forward where the DecimalToFraction(decimal value) is nothing more than a simplified entry point for the first method which provides access to all the components which compose a fraction. If you have a decimal of .325 then divide it by 10 to the power of number of decimal places. Lastly reduce the fraction. And, in this example .325 = 325/10^3 = 325/1000 = 13/40.</p> <p>Next, going the other direction.</p> <p><strong>Convert String Fraction to Decimal Data Type</strong></p> <pre><code>static readonly Regex FractionalExpression = new Regex(@"^(?&lt;sign&gt;[-])?(?&lt;numerator&gt;\d+)(/(?&lt;denominator&gt;\d+))?$"); public static decimal? FractionToDecimal(string fraction) { var match = FractionalExpression.Match(fraction); if (match.Success) { // var sign = Int32.Parse(match.Groups["sign"].Value + "1"); var numerator = Int32.Parse(match.Groups["sign"].Value + match.Groups["numerator"].Value); int denominator; if (Int32.TryParse(match.Groups["denominator"].Value, out denominator)) return denominator == 0 ? (decimal?)null : (decimal)numerator / denominator; if (numerator == 0 || numerator == 1) return numerator; } return null; } </code></pre> <p>Converting back to a decimal is quite simple as well. Here we parse out the fractional components, store them in something we can work with (here decimal values) and perform our division.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload