2009-06-30 37 views
6

trong Excel, =ROUNDUP(474.872126666666, 2) -> 474,88
trong .NET,Excel Roundup vs NET Math.round

kết quả
Math.Round(474.87212666666666666666666666667, 2, MidpointRounding.ToEven) // 474.87 
Math.Round(474.87212666666666666666666666667, 2, MidpointRounding.AwayFromZero) // 474.87 

Khách hàng của tôi muốn làm tròn Excel, là có cách nào tôi có thể nhận 474,88 trong NET?

Cảm ơn rất nhiều

Trả lời

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

Giải pháp này sẽ bao gồm các luồng hạnh phúc khá tốt. Thật không may nó sẽ không hoạt động chính xác cho các số âm, nó sẽ không hoạt động chính xác cho số chữ số âm (mà excel hỗ trợ) và nó sẽ không hoạt động chính xác khi "số" tiếp cận các giá trị lớn như Double.Max, vì bạn đang nhân một giá trị lớn và nó sẽ nằm ngoài phạm vi. –

1

Math.Ceiling là những gì bạn đang tìm kiếm.

+2

Lưu ý rằng OP sẽ cần nhân với 100 trước khi thực hiện Math.Ceiling và sau đó chia cho 100, vì bạn không thể chỉ định # dấu thập phân với hàm này. –

+0

Math.Ceiling (474.87212666666666666666666666667) trả về 475 mà không phải là điều tôi muốn. – nandin

+3

Math.Ceiling (474.87212666666666666666666666667 * 100)/100 công trình. cảm ơn cả hai – nandin

0

Đây là thử nghiệm của tôi về giải pháp hoạt động như chức năng Excel ROUNDUP. tôi đã cố gắng để trang trải các trường hợp như: số thập phân âm, chữ số âm (vâng Excel hỗ trợ đó), giá trị thập phân lớn

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 
     // E.g. |1.23| = |-1.23| = 1.23 
     var absNumber = Math.Abs(number); 

     // Now take the integral part (E.g. for 1.23 is 1) 
     var absNumberIntegralPart = Decimal.Floor(absNumber); 

     // Now take the fractional part (E.g. for 1.23 is 0.23) 
     var fraction = (absNumber - absNumberIntegralPart); 

     // Multiply fractional part by the 10^number of digits we're rounding to 
     // E.g. 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 
     // E.g. 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 
     // E.g. 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 
     // E.g. 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)); 
     } 
0

Đây là tính toán chính xác cho ROUNDUP và 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); 
}