Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Using ToString is about 10x faster than Jon Skeet's solution. While this is reasonably fast, the challenge here (if there are any takers!) is to beat the performance of ToString.</p> <p>The performance results I get from the following test program are: ShowInfo 239 ms FastInfo 25 ms</p> <pre><code>using System; using System.Diagnostics; using System.Globalization; public class Test { static public void Main(string[] x) { Stopwatch sw1 = new Stopwatch(); Stopwatch sw2 = new Stopwatch(); sw1.Start(); for (int i = 0; i &lt; 10000; i++) { ShowInfo(123.4500m); ShowInfo(0m); ShowInfo(0.0m); ShowInfo(12.45m); ShowInfo(12.4500m); ShowInfo(770m); } sw1.Stop(); sw2.Start(); for (int i = 0; i &lt; 10000; i++) { FastInfo(123.4500m); FastInfo(0m); FastInfo(0.0m); FastInfo(12.45m); FastInfo(12.4500m); FastInfo(770m); } sw2.Stop(); Console.WriteLine(sw1.ElapsedMilliseconds); Console.WriteLine(sw2.ElapsedMilliseconds); Console.ReadLine(); } // Be aware of how this method handles edge cases. // A few are counterintuitive, like the 0.0 case. // Also note that the goal is to report a precision // and scale that can be used to store the number in // an SQL DECIMAL type, so this does not correspond to // how precision and scale are defined for scientific // notation. The minimal precision SQL decimal can // be calculated by subtracting TrailingZeros as follows: // DECIMAL(Precision - TrailingZeros, Scale - TrailingZeros). // // dec Precision Scale TrailingZeros // ------- --------- ----- ------------- // 0 1 0 0 // 0.0 2 1 1 // 0.1 1 1 0 // 0.01 2 2 0 [Diff result than ShowInfo] // 0.010 3 3 1 [Diff result than ShowInfo] // 12.45 4 2 0 // 12.4500 6 4 2 // 770 3 0 0 static DecimalInfo FastInfo(decimal dec) { string s = dec.ToString(CultureInfo.InvariantCulture); int precision = 0; int scale = 0; int trailingZeros = 0; bool inFraction = false; bool nonZeroSeen = false; foreach (char c in s) { if (inFraction) { if (c == '0') trailingZeros++; else { nonZeroSeen = true; trailingZeros = 0; } precision++; scale++; } else { if (c == '.') { inFraction = true; } else if (c != '-') { if (c != '0' || nonZeroSeen) { nonZeroSeen = true; precision++; } } } } // Handles cases where all digits are zeros. if (!nonZeroSeen) precision += 1; return new DecimalInfo(precision, scale, trailingZeros); } struct DecimalInfo { public int Precision { get; private set; } public int Scale { get; private set; } public int TrailingZeros { get; private set; } public DecimalInfo(int precision, int scale, int trailingZeros) : this() { Precision = precision; Scale = scale; TrailingZeros = trailingZeros; } } static DecimalInfo ShowInfo(decimal dec) { // We want the integer parts as uint // C# doesn't permit int[] to uint[] conversion, // but .NET does. This is somewhat evil... uint[] bits = (uint[])(object)decimal.GetBits(dec); decimal mantissa = (bits[2] * 4294967296m * 4294967296m) + (bits[1] * 4294967296m) + bits[0]; uint scale = (bits[3] &gt;&gt; 16) &amp; 31; // Precision: number of times we can divide // by 10 before we get to 0 uint precision = 0; if (dec != 0m) { for (decimal tmp = mantissa; tmp &gt;= 1; tmp /= 10) { precision++; } } else { // Handle zero differently. It's odd. precision = scale + 1; } uint trailingZeros = 0; for (decimal tmp = mantissa; tmp % 10m == 0 &amp;&amp; trailingZeros &lt; scale; tmp /= 10) { trailingZeros++; } return new DecimalInfo((int)precision, (int)scale, (int)trailingZeros); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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