double에서 소수 부분 가져 오기


85

소수점 이하의 숫자를 정수 형태로 받고 싶습니다. 예를 들어, 1.05에서 05 만 또는 0.50이 아닌 2.50에서 50 만


15
2.50은 단지 2.5입니다. 나는 당신이 문자열에 대해 이야기하고 있다고 가정합니다.
Tim Schmelter 2012 년

3
항상 소수점 이하 처음 두 자리를 반환합니까? 인 입력 A decimal, float, string, ...?
Greg

3
사용 사례는 다음 번에 양질의 답변을 얻는 데 큰 도움이됩니다.
tmesser

예 숫자 만 towo, 입력은 소수입니다
user1095549는

4
C # 개발 팀은이 매우 일반적인 작업에 Math.DecimalPart (double x) 등과 같은 단일 Math. 함수가 없다는 사실에 당황하고 조치를 취해야합니다. 우리 중 많은 사람들이 자주해야 할 일에는 너무 많은 "이것을 시도 했습니까, 그것에 대해 생각 했습니까"가 있습니다.
philologon

답변:


-21

업데이트 된 답변

여기에서는 동일한 방법으로 3 가지 접근 방식을 제공합니다.

[1] Math.Truncate를 이용한 수학 솔루션

 var float_number = 12.345;
 var result = float_number - Math.Truncate(float_number);

// 입력 : 1.05
// 출력 : "0.050000000000000044"

// 입력 : 10.2
// 출력 : 0.19999999999999929

이것이 예상 한 결과가 아니라면 결과를 원하는 형식으로 변경해야합니다 (하지만 일부 문자열 조작을 다시 수행 할 수 있음).

[2] 승수 사용 [10의 N 제곱 (예 : 10² 또는 10³) 여기서 N은 소수 자릿수입니다.]

       // multiplier is " 10 to the power of 'N'" where 'N' is the number 
       // of decimal places
       int multiplier = 1000;  
       double double_value = 12.345;
       int double_result = (int)((double_value - (int)double_value) * multiplier);

// 출력 345

소수점 이하 자릿수가 고정되지 않은 경우이 방법은 문제를 일으킬 수 있습니다.

[3] "정규식 (REGEX)"사용

문자열로 솔루션을 작성할 때 매우주의해야합니다. 이것은 일부 경우를 제외하고는 바람직하지 않습니다 .

소수 자릿수로 문자열 연산 을 수행 하려는 경우 이것이 바람직합니다.

    string input_decimal_number = "1.50";
    var regex = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
    if (regex.IsMatch(input_decimal_number))
    {
        string decimal_places = regex.Match(input_decimal_number).Value;
    }

// 입력 : "1.05"
// 출력 : "05"

// 입력 : "2.50"
// 출력 : "50"

// 입력 : "0.0550"
// 출력 : "0550"

Regex에 대한 자세한 내용은 http://www.regexr.com/ 에서 찾을 수 있습니다 .


ToString ()은 정수에 대해 소수 부분을 반환하지 않으므로주의하십시오. 즉, MyValue가 3이면 MyValue.ToString ()이 "3"을 반환하므로 Split ( '.') [1]이 발생합니다. 필요한 소수 자릿수에 명시 적으로 형식을 지정하는 것이 좋습니다. MyValue.ToString ( "F2"). Split ( '.') [1]
Alex Beynenson

7
이 솔루션은이 페이지의 다른 솔루션보다 약 2 배 느리며 내 답변보다 약 4 배 느립니다.
tmesser 2014-06-25

1
이 솔루션은 문화에 따라 다릅니다. 예를 들어, 러시아어와 영어-미국에는 다른 소수점 구분 기호 (해당 쉼표와 점)가 있습니다. 따라서이 코드는 다른 문화 설정에서 실패합니다.
Yury Schkatula

2
이 솔루션은 .항상 소수점 구분 기호가 아닌 에서 분할됩니다 (예 : 유럽에서는 소수점 구분 기호가입니다 ,). CultureInfo.Invariant국제화 하려면 추가 해야합니다. 사용하는 것이 더 쉽고 x - Math.Truncate(x)그 결과에 마술을 부리지 만.
Abel

3
@Kiquenet 7 번째 개정이기 때문에. 이것이 원래 답변이었습니다. stackoverflow.com/revisions/19374418/1
Manfred Radlwimmer 2017-08-09

199

가장 좋은 방법은 다음과 같습니다.

var floatNumber = 12.5523;

var x = floatNumber - Math.Truncate(floatNumber);

원하는대로 변환 할 수있는 결과


10
이 문자열 조작에 대한 모든 지루한 비료없이 허용 대답, 수학 질문에 수학 솔루션이어야한다
johnc

20
이 솔루션에는 "문제"가 있다고 생각합니다. floatNumber가 "10.2"이면 변수 x는 "0.19999999999999929"와 같습니다. 예상대로 작동하더라도 결과는 "2"가 아니라 "0.2"가됩니다.
Dherik 2014

4
@Dherik Float 및 Double 값은 항상 마지막 소수 자릿수에 빼기시 작은 오류가 있습니다. 그것들을 중요하다고 생각해서는 안됩니다. 실제로 이러한 종류의 정밀도가 필요한 경우 Decimal 유형을 사용해야합니다. Decimal로 전환 할 수없는 경우 (또는 원하지 않는 경우), 예상되는 정밀도를 어떻게 든 추적하고 비교 작업에서이를 고려해야합니다. 보통 소수점 4 자리를 사용하지만 예외가있을 수 있습니다.
philologon

에서 msdn.microsoft.com/en-us/library/...는 "일부 번호가 정확히 분수 바이너리 값으로 표현 될 수 없기 때문에 부동 소수점 숫자를 할 수있는 경우에만 대략적인 실수"
philologon

1
최종 의견 : Math.Truncate를 사용하는 것은 이러한 상황에 대한 Math 라이브러리 작성자의 의도였습니다. @Matterai의 대답은 받아 들여 져야합니다.
philologon 2015 년

81
var decPlaces = (int)(((decimal)number % 1) * 100);

이것은 당신의 숫자가 소수점 두 자리 만 가지고 있다고 가정합니다.


1
(318.40d % 1) * 100출력 39.9999999999977, 캐스트를 사용하여 반올림 오류를 해결할 수 있습니다.var decPlaces = (int)(((decimal)number % 1) * 100);
orad

@orad 좋은 호출-부동 소수점 숫자는 항상 약간의 부정확성이 있으므로 일관된 동작을 보장하기 위해 캐스팅하는 것이 매우 신중합니다. Matterai가 여전히 기술적으로 더 정확하지만 내 답변을 업데이트하겠습니다.
tmesser

27

'Math.Truncate'접근 방식보다 더 깨끗하고 빠른 솔루션이 있습니다.

double frac = value % 1;

7
참고 : 음수 값의 경우 음수입니다 . -12.34 % 1 => -0.33999999999999986
Alex Poca

16

반올림 문제가없는 솔루션 :

double number = 10.20;
var first2DecimalPlaces = (int)(((decimal)number % 1) * 100);
Console.Write("{0:00}", first2DecimalPlaces);

출력 : 20

십진수로 캐스트하지 않으면 19.

또한:

  • 318.40출력 : 40(대신 39)
  • 47.612345출력 : 61(대신 612345)
  • 3.01출력 : 01(대신 1)

금융 번호로 작업하는 경우 (예 :이 경우 거래 금액 의 센트 부분 을 얻으려는 경우 ) 항상 decimal데이터 유형을 사용하십시오 .

최신 정보:

다음은 문자열로 처리하는 경우에도 작동합니다 (@SearchForKnowledge의 답변을 기반으로 함).

10.2d.ToString("0.00", CultureInfo.InvariantCulture).Split('.')[1]

그런 다음을 사용 Int32.Parse하여 int로 변환 할 수 있습니다 .


1
모드의 사람을위한 엄지 손가락
Ivandro Jao

나는 이것을 사용했다 ... 10.2d.ToString ( "0.00", CultureInfo.InvariantCulture) .Split ( '.') [1]
Ziggler

10

더 좋은 방법 -

        double value = 10.567;
        int result = (int)((value - (int)value) * 100);
        Console.WriteLine(result);

출력-

56

2
테스트하지 않았지만 이것은 플로트 부정확성으로 고통받습니다.
mafu

10.20그것을 위해 출력 19됩니다. 내 대답을 참조하십시오.
orad

9

가장 간단한 변형은 아마도 Math.truncate ()입니다.

double value = 1.761
double decPart = value - Math.truncate(value)

2

이 스레드가 늙어 가고 있다고 생각하지만 아무도 Math를 언급하지 않았다는 것을 믿을 수 없습니다.

//will always be .02 cents
(10.02m - System.Math.Floor(10.02m))

슈퍼 게으른 :double fract(double x) { return x - System.Math.Floor(x); }
Felipe Gutierrez

1
var result = number.ToString().Split(System.Globalization.NumberDecimalSeparator)[2]

문자열로 반환하고 (항상 int로 다시 캐스트 할 수 있음) 숫자에 "."가 있다고 가정합니다. 어딘가에.


1
int last2digits = num - (int) ((double) (num /  100) * 100);

문제는 처음 2 자리 십진수를 얻는 것입니다. 318.401567d솔루션 이 예상되는 0.401567곳에 번호를 매기 십시오 40.
orad

0
    public static string FractionPart(this double instance)
    {
        var result = string.Empty;
        var ic = CultureInfo.InvariantCulture;
        var splits = instance.ToString(ic).Split(new[] { ic.NumberFormat.NumberDecimalSeparator }, StringSplitOptions.RemoveEmptyEntries);
        if (splits.Count() > 1)
        {
            result = splits[1];
        }
        return result;
    }

0

비슷한 상황에 대해 작성한 확장 방법이 있습니다. 내 응용 프로그램은 숫자의 정수 구성 요소가 연도를 나타내고 분수 구성 요소가 월을 나타내는 2.3 또는 3.11 형식의 숫자를받습니다.

// Sample Usage
int years, months;
double test1 = 2.11;
test1.Split(out years, out months);
// years = 2 and months = 11

public static class DoubleExtensions
{
    public static void Split(this double number, out int years, out int months)
    {
        years = Convert.ToInt32(Math.Truncate(number));

        double tempMonths = Math.Round(number - years, 2);
        while ((tempMonths - Math.Floor(tempMonths)) > 0 && tempMonths != 0) tempMonths *= 10;
        months = Convert.ToInt32(tempMonths);
    }
}

0

오버 헤드 일 수 있지만 작동합니다.

double yourDouble = 1.05;
string stringForm = yourDouble.ToString();
int dotPosition = stringForm.IndexOf(".");
decimal decimalPart = Decimal.Parse("0" + stringForm.Substring(dotPosition));

Console.WriteLine(decimalPart); // 0.05

0
 string input = "0.55";
    var regex1 = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
    if (regex1.IsMatch(input))
    {
        string dp= regex1.Match(input ).Value;
    }

1
정규식이 문제 해결에 어떻게 도움이되는지에 대한 설명을 추가 할 수 있다면 좋을 것입니다.
Cleptus

-1

double을 문자열로 변환 한 후 함수 .를 사용하여 소수점을 얻으려는 double 에서 점 을 제거하여 Remove()필요한 작업을 수행 할 수 있습니다.

이중 가지고 고려 _Double의 값을 0.66781, 다음 코드는 점 이후의 숫자 만 표시 할 .수 있습니다66781

double _Double = 0.66781; //Declare a new double with a value of 0.66781
string _Decimals = _Double.ToString().Remove(0, _Double.ToString().IndexOf(".") + 1); //Remove everything starting with index 0 and ending at the index of ([the dot .] + 1) 

또 다른 해결책

Path크로스 플랫폼 방식으로 문자열 인스턴스에 대한 작업을 수행 하는 클래스 를 사용할 수도 있습니다.

double _Double = 0.66781; //Declare a new double with a value of 0.66781
string Output = Path.GetExtension(D.ToString()).Replace(".",""); //Get (the dot and the content after the last dot available and replace the dot with nothing) as a new string object Output
//Do something

-2

정규식 사용 : Regex.Match("\.(?\d+)")내가 틀렸다면 누군가 나를 고쳐주세요.


별로 인기가 없음 Regex.Match 있지만, 소수의 값려고 다음과 같은 오류받은ArgumentException was unhandled: parsing "\.(?\d+)" - Unrecognized grouping construct.
Picrofo 소프트웨어

-2

매우 간단합니다

       float moveWater =  Mathf.PingPong(theTime * speed, 100) * .015f;
       int    m = (int)(moveWater);
       float decimalPart= moveWater -m ;

       Debug.Log(decimalPart);

-2

왜 사용하지 int y = value.Split('.')[1];않습니까?

Split()함수는 값을 별도의 콘텐츠로 분할 1하고은 다음 두 번째 값을 출력합니다..


작동합니다 :Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))
orad

문자열 조작을 위해 문자열로 캐스팅하기 때문입니다. 나는 이것이 얼마나 느리고 낭비인지 깨닫지 못한다고 생각합니다.
dmarra
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.