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.