Ejemplo n.º 1
0
        private static double TryRoundDoubleQuick(double value, int decimals, MidpointRounding midpointRounding)
        {
            // Try a fast round based on ideas from: http://www.coderanch.com/t/582520/java/java/fast-method.

            // The problem is that when we multiply by a power of ten we might - due to inherent double
            // inaccuaracy - end up with a value that rounds differently to what we expect.
            // Therefore we round two values just slighly larger/smaller that the value
            // we try to round. If the results are equal, we're done. If they are not,
            // we fail with double.NaN.

            if (RoundPower10Double == null)     // can't use static initializer in a framework extension class.
            {
                RoundPower10Double = new[] { 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15 }
            }
            ;

            var    factor    = RoundPower10Double[decimals];
            double y         = value * factor;
            var    threshold = Math.Ulp(y) * RoundSafetyFactor;

            double d1, d2;

            if (midpointRounding == MidpointRounding.AwayFromZero)
            {
                if (y < 0)
                {
                    y -= 0.5;
                    d1 = Math.Ceiling(y + threshold);
                    d2 = Math.Ceiling(y - threshold);
                }
                else
                {
                    y += 0.5;
                    d1 = Math.Floor(y + threshold);
                    d2 = Math.Floor(y - threshold);
                }
            }
            else
            {
                d1 = Math.Rint(y + threshold);
                d2 = Math.Rint(y - threshold);
            }

            if (d1 == d2)
            {
                return(d1 / factor);
            }

            return(double.NaN);
        }