2012-07-02 3 views
2

.NET에는 .NET이 내장되어 있지만 외부 호출이라고 알고 있습니다. 왜 그 사람이 누군지 압니까?C#에서 강력한 자르기 메서드를 구현하는 방법은 무엇입니까?

하지만 실제 문제는 사용자가 몇 자릿수를 유지할 지 지정할 수있는 처음부터 잘라내기를 구현하는 방법입니다. 숫자에 100을 곱한 다음이를 같은 양으로 충분히 나누고 있습니까? 아니면 더 나은 구현이 있습니까? 같은

뭔가 :

Truncate(12.3456789, 3); 
// returns 12.345 

답변

0
var result = Math.Round(12.3456789, 3); 

Math.Round Method (Double, Int32)

+1

맞지 않습니다. 그것은'12.346'으로 반올림합니다. –

+0

THank하지만 내부적으로 동일한 SplitFractionDouble 메서드도 호출합니다. –

+0

@Ramhound 나는 그 방법에 "반대"하지 않고, 나는 단지 내 자신을 구현하고 싶다. –

-1

그것은 당신이 자르기가 decmial 값을 유지해야한다고 생각하는 이유를 명확하지 않다.

.NET 내의 기본 방법은 다음 내용에서 설명된다 : d의

정수 부분; 즉, 자릿수가 버린 이후에 남아있는 번호입니다.

당신이 원하는 것은 double/decmial 값의 출력 문자열을 형식화하거나 Math.Round (double, int) 함수를 대신 사용하는 것 같습니다.

당신은 사용할 수 있습니다 : 중복 질문 중 하나에서

double num = 2.22939393; num = Convert.ToDouble(num.ToString("#0.000")); 

:이 이해

public static decimal TruncateToDecimalPlace(this decimal numberToTruncate, int decimalPlaces) 
{  
     decimal power = (decimal)(Math.Pow(10.0, (double)decimalPlaces));  
     return Math.Truncate((power * numberToTruncate))/power; 
} 

는 여전히 Truncate 방법을 사용합니다. 숫자의 십진수 값을 유지하는 Truncate 메서드가 필요하고 기본 제공 Truncate 메서드가 필요하기 때문에이 코드 만 제공했습니다.

당신은 항상 그냥이를 사용할 수 있습니다 : 나는

 private static unsafe double InternalRound(double value, int digits, MidpointRounding mode) { 
      if (Abs(value) < doubleRoundLimit) { 
       Double power10 = roundPower10Double[digits]; 
       value *= power10; 
       if (mode == MidpointRounding.AwayFromZero) {     
        double fraction = SplitFractionDouble(&value); 
        if (Abs(fraction) >= 0.5d) { 
         value += Sign(fraction); 
        } 
       } 
       else { 
        // On X86 this can be inlined to just a few instructions 
        value = Round(value); 
       } 
       value /= power10; 
      } 
      return value; 
      }   


    public static double Round(double value, int digits) 
     { 
      if ((digits < 0) || (digits > maxRoundingDigits)) 
       throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); 
      return InternalRound(value, digits, MidpointRounding.ToEven);      
     } 

    public static double Round(double value, MidpointRounding mode) { 
     return Round(value, 0, mode); 
     } 

     public static double Round(double value, int digits, MidpointRounding mode) { 
      if ((digits < 0) || (digits > maxRoundingDigits)) 
       throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); 
      if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) {    
       throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode"); 
      } 
      return InternalRound(value, digits, mode);       
     } 

     public static Decimal Round(Decimal d) { 
     return Decimal.Round(d,0); 
     } 

     public static Decimal Round(Decimal d, int decimals) { 
     return Decimal.Round(d,decimals); 
     } 

     public static Decimal Round(Decimal d, MidpointRounding mode) { 
     return Decimal.Round(d, 0, mode); 
     } 

     public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) { 
     return Decimal.Round(d, decimals, mode); 
     } 


공공 정적 진수 층 (10 진 d)를 말할 수있는

Math.Round는 {에서 을 SplitFractionDouble를 호출하지 않습니다 return Decimal.Floor (d); }

[MethodImplAttribute (MethodImplOptions.InternalCall)] public static extern double Floor (double d);

2

IEEE 부동 소수점 정수를보고 싶을 것입니다.

당신은 다음과 같은 숫자를 수정 unsafe 코드를 사용할 수 있습니다

unsafe 
{ 
    double* pValue = &value; 
    var asLong = *(long*)pValue; 
    do whatever you want with asLong, e.g. bit-masking it, etc.; 
} 

을 '왜'에 관해서는 다음 Shared Source CLI 단서를 제공 할 수 있지만 내가 아무 생각이 없습니다. 내 은 성능 최적화로 인해이 될 것입니다.

2

고전적인 방법 :

var x = 1.2345678; 
var tr = 4; 

var truncated = (int) (x * Math.Pow(10, tr))/Math.Pow(10, tr); 

는 1.2345을 줄 것이다;

+0

고마워, 너 그렇게 할 수 있을지 몰랐어. –

+0

@ JoanVenge 당신은 그렇게 말하고 아직 OP 자체에서 가능한지 묻습니다. 이것은 단순히 그 접근법을 구현 한 것입니다. * "100을 곱하여 숫자를 곱한 다음 같은 양으로 나누고 있습니까?"* – Servy

+0

아니요. 나는 어떤 권력도 언급하지 않았다. –

1

다음은 어떻게 수행할까요? C++에서는 C#에서도 정수형으로 캐스팅하여 부동 소수점 숫자의 정수 부분을 얻을 수 있다고 생각합니다.

double Truncate (double num, int dig) 
{ 
    if (dig > 15) dig = 15; // Don't overflow 
    long p = Math.Pow (10, dig); 

    // Save the integer part, so that we don't overflow 
    long integer_part = (long)num; 

    // Fractional part * 10^dig 
    double frac = (num - Convert.ToDouble(integer_part)) * p; 
    long frac_trunc = (long)frac; 

    // Final result 
    double result = Convert.ToDouble(integer_part) + (Convert.ToDouble(frac_trunc)/p); 
    return result; 
} 

100 말하여 숫자를 곱한 후 동일한 충분한 양으로 나누어인가?

큰 숫자 또는 높은 자릿수가 있으면 쉽게 오버플로 할 수 있으므로 이상한 결과가 나올 수 있으므로주의해야합니다.

+0

* 부동 소수점 숫자를 정수형으로 변환하여 정수 부분을 얻을 수 있습니다. * 너무 큰 경우 어떻게해야합니까? 그렇게 된 적이 있습니까? (나는 체크하지 않고 단지 묻는다.) – Mehrdad

+0

MSDN에 따르면 double은 64 비트 부동 소수점 숫자 (또는 15-16 자리)이므로 충분히 길어야한다. – Tibi

+0

@Mehrdad 각 부동 소수점 유형과 동일한 바이트 수의 정수 유형이 있습니다. 그것은'int'를 사용하는 것을 항상 의미하는 것은 아닙니다.'long'을 사용하는 것을 의미 할 수도 있습니다. – Servy

관련 문제