Decimal 숫자의 정수 부분을 얻는 가장 좋은 방법


89

십진수의 정수 부분을 반환하는 가장 좋은 방법은 무엇입니까 (C #에서)? (이것은 int에 맞지 않을 수있는 매우 큰 수에 대해 작동해야합니다).

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

그 목적은 다음과 같습니다. db의 십진수 (30,4) 필드에 삽입하고 필드에 비해 너무 긴 숫자를 삽입하지 않도록하고 싶습니다. 소수의 정수 부분 길이를 결정하는 것은이 연산의 일부입니다.


당신은 int 부분을 얻을 수 없습니다. 정수 부분을 얻고 분수 부분을 버릴 수 있습니다. Decimal의 정수 부분은 쉽게 int를 오버플로하고 던지거나 감싸서 코드를 조용히 죽일 수 있습니다.

1
그렇기 때문에이 질문이보기만큼 간단하지 않습니다. 작은 수만큼 안정적으로 매우 큰 수에 대해 작동하려면 이것이 필요합니다. 그러나 "정수"가 "int"보다 정확합니다. 위에서 다시 말하겠습니다.
Yaakov Ellis

답변:


212

그건 그렇고, (int) Decimal.MaxValue는 오버플로됩니다. 소수가 int 상자에 넣을 수 없을 정도로 너무 커서 소수의 "int"부분을 얻을 수 없습니다. 방금 확인했습니다 ... 오랫동안 너무 큽니다 (Int64).

Decimal 값의 비트를 점의 왼쪽에 넣으려면 다음을 수행해야합니다.

Math.Truncate(number)

값을 ... A DECIMAL 또는 DOUBLE로 리턴하십시오.

편집 : 잘라내 기는 확실히 올바른 기능입니다!


따라서 결과는 소수점 뒤에는 아무것도 가지지 않는 10 진수 또는 2 배이지만 결과를 "int"(소수점 없음)로 저장하는 객체가 내장되어 있지 않아 약간 절름발이로 보입니다.
Coops

@CodeBlend : 정확성을 잃고 자하는 욕구를 중심으로 프레임 워크를 디자인해야하는 요구가 많지 않습니다.

@CodeBlend : 숫자의 소수 값을 잘라 내기 때문에 여전히 정밀도가 떨어집니다. 당신이 무엇을 얻고 있는지 확실하지 않습니다.

이것이 작동할지 여부는 확실하지 않습니다. Math.Truncate (-5.99999999999999999)는 나를 위해 -6.0을 반환하기 때문에 ... !!
Bharat Mori

@Bharat Mori : 자르기 전에 -5.99999999999999999가 -6.0으로 반올림 된 것 같습니다. 접미사 "m"으로 시도하면 작동합니다. Math.Truncate (-5.99999999999999999m)는 -5를 제공합니다.
Henry


4

무엇을하는지에 따라 다릅니다.

예를 들면 :

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

또는

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

기본값은 항상 전자입니다. 이는 놀라 울 수 있지만 매우 의미가 있습니다. 입니다.

명시적인 캐스트는 다음을 수행합니다.

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

당신이 말한 방식에서 이것은 당신이 원하는 것이 아닌 것처럼 들립니다. 당신은 매번 그것을 바닥에 놓고 싶습니다.

나는 할것이다:

Math.Floor(Math.Abs(number));

또한 당신의 크기를 확인하십시오 decimal-그들은 상당히 클 수 있으므로 long.


(long) Decimal.MaxValue가 오버플로됩니다.

공정한 점-이것이 Math.Truncate (decimal)이 십진수를 반환하는 이유라고 생각합니다.
Keith

C #에서 int 로의 캐스팅은 반올림되지 않으므로 (int) 0.6f는 0이되고 (int) 343564565.5는 6이 아닌 5로 끝납니다. 여기에서 시도하십시오 : repl.it/repls/LuxuriousCheerfulDistributeddatabase
sschmidTU

0

다음과 같이 캐스트하면됩니다.

int intPart = (int)343564564.4342

나중에 계산에서 십진수로 계속 사용하려면 Math.Truncate (또는 음수에 대한 특정 동작을 원하는 경우 Math.Floor 가능)가 원하는 함수입니다.


5
이것은 잘못된 잘못된 것입니다. 결과가 Int32가 보유 할 수있는 것보다 크면 예외를 던지거나 (심지어 더 나쁘다 !!!) 조용히 오버플로하고 다시 래핑하여 사용자가 알지 못하는 사이에 완전히 잘못된 결과를 제공합니다.

2
아니, 틀린게 아니야 . 매우 큰 소수 / 부동 소수점 값에는 유효하지 않지만 대부분의 상황에서는 완벽합니다. 코딩 할 때 숫자가 충분히 낮도록 제한되는 경우가 많으므로 문제가되지 않습니다. 또한 모든 값에 대해 작동하는 Math.Truncate 솔루션을 제공했습니다.
Noldorin

2
왜 나 한테 화가 났는지 알 겠어. 사실은 당신의 대답이 틀렸다는 것입니다. 당신은 그에게 기회를 잡으라고 말하는 것입니다. 왜냐하면 많은 숫자가 작기 때문입니다. 감당할 어리석은 위험입니다. 답을 편집하고 Math.Truncate를 제외한 모든 것을 제거해야합니다.

1
그들이 ASSUME에 대해 뭐라고 말하는지 알고 있습니다. 또한 당신의 가정은 특히 끔찍합니다. 그게 염증인가요? 그렇게 말할 수있을 것 같아요. 또한 누군가에게 어리석은 일을하여 길을 따라 문제를 일으킬 수 있다고 말하는 것은 비 윤리적이라고 생각하지 않더라도 선동적이라고 말할 수 있습니다.

1
사실 내가 오해의 소지가있는 대답을하려고한다면 그것은 잘못된 것입니다. 그렇기 때문에 나는 단순히 도우려고 노력하고있었습니다. 내가 약간의 오해를 범하거나 질문을 충분히 이해하지 못한다면 그것은 충분히 공평합니다. 그것은 범죄가 아닙니다. 그렇다면 우리는 왜 지금 논쟁하고 있습니까? 우리 모두는 Truncate가 정답이라는 데 동의합니다.
Noldorin

0

값과 소수 부분 값을 분리하는 매우 쉬운 방법입니다.

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

s는 소수 부분 = 5이고
i는 정수 = 3 인 값입니다.


1
위의 상위 답변을 참조하십시오. 이 (int)Decimal.MaxValue오버플로 때문에 작동하지 않습니다 .
Yaakov Ellis

0

나는 당신을 돕길 바랍니다.

/// <summary>
/// Get the integer part of any decimal number passed trough a string 
/// </summary>
/// <param name="decimalNumber">String passed</param>
/// <returns>teh integer part , 0 in case of error</returns>
private int GetIntPart(String decimalNumber)
{
    if(!Decimal.TryParse(decimalNumber, NumberStyles.Any , new CultureInfo("en-US"), out decimal dn))
    {
        MessageBox.Show("String " + decimalNumber + " is not in corret format", "GetIntPart", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return default(int);
    } 

    return Convert.ToInt32(Decimal.Truncate(dn));
}

-2
   Public Function getWholeNumber(number As Decimal) As Integer
    Dim round = Math.Round(number, 0)
    If round > number Then
        Return round - 1
    Else
        Return round
    End If
End Function

1
8 년 이상 전에 게시 된 승인 된 답변은이 답변이 잘못된 이유를 설명합니다. 의 범위가의 범위 decimal보다 훨씬 큽니다 int. 또한 이것은 VB 질문이 아닙니다.
Joe Farrell

@JoeFarrell-답변이 틀렸다고 생각되면 효과에 댓글을 남기는 것 외에도 반대 투표를 고려할 수 있습니다. 그러나 플래그를 지정하지 마십시오 (내가 가지고 있다고 말하는 것이 아닙니다). 그것은 시도 질문에 대답하기 위해. 언어가 틀렸을 수도 있고 VB에서도 틀릴 수도 있지만 시도입니다. 예를 들어, " 답변이 잘못된 질문에 대한 대답은 대답이 아닙니까? "를 참조하십시오.
Wai Ha Lee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.