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); }