Excel RoundUp vs .NET Math.Round

在Excel中, =ROUNDUP(474.872126666666, 2) – > 474.88
在.NET中,

 Math.Round(474.87212666666666666666666666667, 2, MidpointRounding.ToEven) // 474.87 Math.Round(474.87212666666666666666666666667, 2, MidpointRounding.AwayFromZero) // 474.87 

我的客户想要Excel四舍五入的结果,有什么办法,我可以在.NET中获得474.88?

非常感谢

 double ROUNDUP( double number, int digits ) { return Math.Ceiling(number * Math.Pow(10, digits)) / Math.Pow(10, digits); } 

Math.Ceiling是你在找什么。

这是我的一个解决scheme的行为像Excel ROUNDUP函数的尝试。 我试图涵盖例如负数十进制数,负数(是Excel支持),大十进制值

 public static decimal RoundUp(decimal number, int digits) { if (digits > 0) { // numbers will have a format like +/-1.23, where the fractional part is optional if numbers are integral // Excel RoundUp rounds negative numbers as if they were positive. // To simulate this behavior we will use the absolute value of the number // Eg |1.23| = |-1.23| = 1.23 var absNumber = Math.Abs(number); // Now take the integral part (Eg for 1.23 is 1) var absNumberIntegralPart = Decimal.Floor(absNumber); // Now take the fractional part (Eg for 1.23 is 0.23) var fraction = (absNumber - absNumberIntegralPart); // Multiply fractional part by the 10 ^ number of digits we're rounding to // Eg For 1.23 with rounded to 1 digit it will be 0.23 * 10^1 = 2.3 // Then we round that value UP using Decimal.Ceiling and we transform it back to a fractional part by dividing it by 10^number of digits // Eg Decimal.Ceiling(0.23 * 10) / 10 = Decimal.Ceiling(2.3) / 10 = 3 / 10 = 0.3 var tenPower = (decimal)Math.Pow(10, digits); var fractionRoundedUp = Decimal.Ceiling(fraction * tenPower) / tenPower; // Now we add up the absolute part with the rounded up fractional part and we put back the negative sign if needed // Eg 1 + 0.3 = 1.3 return Math.Sign(number) * (absNumberIntegralPart + fractionRoundedUp); } else if (digits == 0) { return Math.Sign(number) * Decimal.Ceiling(Math.Abs(number)); } else if (digits < 0) { // negative digit rounding means that for RoundUp(149.12, -2) we will discard the fractional part, shift the decimal point on the left part 2 places before rounding up // then replace all digits on the right of the decimal point with zeroes // Eg RoundUp(149.12, -2). Shift decimal point 2 places => 1.49. Now roundup(1.49) = 2 and we put 00 instead of 49 => 200 var absNumber = Math.Abs(number); var absNumberIntegralPart = Decimal.Floor(absNumber); var tenPower = (decimal)Math.Pow(10, -digits); var absNumberIntegraPartRoundedUp = Decimal.Ceiling(absNumberIntegralPart / tenPower) * tenPower; return Math.Sign(number)*absNumberIntegraPartRoundedUp; } return number; } [TestMethod] public void Can_RoundUp_Correctly() { Assert.AreEqual(1.466m, MathExtensions.RoundUp(1.4655m, 3)); Assert.AreEqual(-1.466m, MathExtensions.RoundUp(-1.4655m, 3)); Assert.AreEqual(150m, MathExtensions.RoundUp(149.001m, 0)); Assert.AreEqual(-150m, MathExtensions.RoundUp(-149.001m, 0)); Assert.AreEqual(149.2m, MathExtensions.RoundUp(149.12m, 1)); Assert.AreEqual(149.12m, MathExtensions.RoundUp(149.12m, 2)); Assert.AreEqual(1232m, MathExtensions.RoundUp(1232, 2)); Assert.AreEqual(200m, MathExtensions.RoundUp(149.123m, -2)); Assert.AreEqual(-200m, MathExtensions.RoundUp(-149.123m, -2)); Assert.AreEqual(-20m, MathExtensions.RoundUp(-12.4655m, -1)); Assert.AreEqual(1.67m, MathExtensions.RoundUp(1.666666666666666666666666666m, 2)); Assert.AreEqual(1000000000000000000000000000m, MathExtensions.RoundUp(999999999999999999999999999m, -2)); Assert.AreEqual(10000000000000m, MathExtensions.RoundUp(9999999999999.999m, 2)); } 

这是ROUNDUP和ROUNDDOWN的正确计算:

 private static object RoundDown(List<Expression> p) { var target = (decimal)p[0].Evaluate(); var digits = (decimal)p[1].Evaluate(); if (target < 0) return (Math.Ceiling((double)target * Math.Pow(10, (int)digits)) / Math.Pow(10, (int)digits)); return Math.Floor((double)target * Math.Pow(10, (int)digits)) / Math.Pow(10, (int)digits); } private static object RoundUp(List<Expression> p) { var target = (decimal)p[0].Evaluate(); var digits = (decimal)p[1].Evaluate(); if (target < 0) return (Math.Floor((double)target * Math.Pow(10, (int)digits)) / Math.Pow(10, (int)digits)); return Math.Ceiling((double)target * Math.Pow(10, (int)digits)) / Math.Pow(10, (int)digits); }