10 진수 / 더블이 정수인지 확인하는 방법?


225

소수 또는 이중 값이 정수인지 어떻게 알 수 있습니까?

예를 들면 다음과 같습니다.

decimal d = 5.0; // Would be true
decimal f = 5.5; // Would be false

또는

double d = 5.0; // Would be true
double f = 5.5; // Would be false

나는 이것이 내가 출력에 사용하여 값을 원한다면 프로그래밍 결정할 수 있도록 알고 싶은 이유 .ToString("N0")또는 .ToString("N2"). 소수점 값이 없으면 표시하고 싶지 않습니다.

답변:


410

부동 소수점 숫자의 경우 n % 1 == 0일반적으로 소수점을 지난 것이 있는지 확인하는 방법입니다.

public static void Main (string[] args)
{
    decimal d = 3.1M;
    Console.WriteLine((d % 1) == 0);
    d = 3.0M;
    Console.WriteLine((d % 1) == 0);
}

산출:

False
True

업데이트 : @Adrian Lopez가 아래 언급했듯이 작은 값을 비교epsilon하면 부동 소수점 계산 오류 계산이 무시됩니다. 문제는double값에관한 것이므로아래는 더 부동 소수점 계산 증명 답변입니다.

Math.Abs(d % 1) <= (Double.Epsilon * 100)

96
숫자가 정수로 시작될 때 작동하지만 숫자가 부동 소수점 계산의 결과 일 때 반드시 그런 것은 아닙니다. epsion이 작은 값인 "(d % 1) <epsilon"과 같은 것은 어떻습니까?
Adrian Lopez

9
이 글에서 가장 좋은 답변은 받아 들여진 답변이 아니라 의견이라는 것이 부끄러운 일입니다. 좋은 사람 애드리안.
starskythehutch

13
또한 위의 Adrian의 의견이 가장 좋은 답변이라고 생각합니다. 공식적인 C # 코드에 그의 조언을 넣으려면 : if (Math.Abs ​​(n % 1) <Double.Epsilon) {// n이 정수이면 무언가를하십시오}.
Ruben Ramirez Padron

7
IMHO, 계수 연산자와 부동 소수점 숫자는 어떤 식 으로든 혼합되지 않습니다. 제안 된 코드는 사용 된 키 입력 수를 감안할 때 매우 혼란스럽고 .NET 언어 외부에서는 거의 작동하지 않습니다. 나는 그것이 올바른 방법보다 훨씬 느리다는 것을 확신합니다 (아무 구분도 사용하지 않음). 이를 수행하는 올바른 방법은을 사용하는 것 Math.Abs(d-(int)d) < double.Epsilon입니다. 우리 모두 대학에서 첫 프로그래밍 수업 첫 주에 배웠어야했듯이.
krowe2

9
실제로, 질문이 언급 된 바와 같이,이 답변은 정확하고 주석은 잘못되었습니다. OP는 double이 수학적인 목적을위한 정수인지 아닌지, 그것을 표시하는 방법을 알고 싶어합니다. 만 정확한 정수 값은 소수점없이 표시되어야합니다. 또한 부동 소수점에 유용하지 않고 .NET 외부에서 작동하지 않는 mod에 대한 의견은 잘 알려지지 않았습니다. 그리고 (int)d대부분의 이중 가치에 대한 예외를 던질 재앙입니다.
Jim Balter

49

이를 수행하는 방법에는 여러 가지가 있습니다. 예를 들면 다음과 같습니다.

double d = 5.0;
bool isInt = d == (int)d;

모듈로를 사용할 수도 있습니다.

double d = 5.0;
bool isInt = d % 1 == 0;

이것들 중 하나가 다른 것보다 빠를까요? 성능에 민감한 상황 에서이 작업을 수행하고 싶습니다.
바질

@Basil-상황에 따라 다릅니다. 당신은 스스로 타이밍을 정하고 판단해야합니다.
Erik Funkenbusch

4
Math.Abs(d-(int)d) < double.Epsilon보다 안전한d == (int)d
Reactgular

3
@MathewFoscarini-혼란스러워합니다. 16.1-6.1의 결과가 정수가 아니기 때문에 false로 설정합니다. 요점은 주어진 값이 int인지 확인하는 것이지, 대략 int 인 것이 int 인 경우가 아닙니다.
Erik Funkenbusch

1
@MathewFoscarini-예, int는 10 진수 값이없는 숫자 (또는 10 진수 값 0)입니다. 16.1-6.1은 10 진수 값을 생성하지 않으며 IEEE 부동 소수점 형식 문제로 인해 0이 아닌 매우 작은 값입니다. 반올림 값이 정확하지 않다고 가정하면 숫자가 10 진수 값을 가질 지 여부를 알 수있는 방법은 없습니다. 문제의 목적은 부동 소수점 숫자가 정수인지 아닌지 정수가 아닌지를 아는 것입니다.
Erik Funkenbusch 2012 년

21

이건 어때요?

public static bool IsInteger(double number) {
    return number == Math.Truncate(number);
}

의 동일한 코드입니다 decimal.

마크 바이어스 (Mark Byers)는 실제로 좋은 지적을했습니다. 이것은 실제로 당신 원하는 것이 아닐 수도 있습니다 . 당신이 경우 정말 걱정 것은 숫자가 정수입니다 가장 가까운 소수 둘째 자리까지 반올림 여부 , 대신이 작업을 수행 할 수 있습니다 :

public static bool IsNearlyInteger(double number) {
    return Math.Round(number, 2) == Math.Round(number);
}

1
아마도 솔루션을 업데이트하고 추가 && 수 <int.MaxValue && 번호> int.MinValue
월터 Vehoeven

12

제안 된 솔루션이 간단한 예제에서 작동하는 것처럼 보이지만 일반적으로이 작업을 수행하는 것은 좋지 않습니다. 숫자는 정확히 정수가 아니지만 형식을 지정할 때 얻을 수있는 정수에 가깝습니다 1.000000. 이론적으로 정확히 1을 계산해야하지만 실제로 반올림 오류로 인해 숫자에 거의 근접하지만 정확히 같지 않은 계산을 수행하면 발생할 수 있습니다.

대신, 먼저 형식을 지정하고 문자열이 마침표로 끝나고 0이 오면 제거하십시오. 스트립 후행 0을 자동으로 사용할 수있는 형식도 있습니다. 이것은 당신의 목적에 충분할 것입니다.

double d = 1.0002;
Console.WriteLine(d.ToString("0.##"));
d = 1.02;
Console.WriteLine(d.ToString("0.##"));

산출:

1
1.02

@Mark는 흥미 롭다. 후행 0을 제거하는 형식의 예가 있습니까?
Jim Geurts

나는 그것이 더 안전하고 OP 가해 야 할 일에 동의하지만 가치가 소수 부분인지 아닌지에 대한 더 좁은 (그러나 더 흥미로운) 질문에 대한 대답은 아닙니다.
Clifford

3
@Clifford : 나는 보통 제목이 말한 것이 아니라 OPs 문제를 해결하는 가장 좋은 방법에 따라 답변하려고합니다. 제목은 문제에 대한 정확한 설명이 아닙니다.
Mark Byers

+1 float 또는 double을 테스트하려고하면 반올림 및 정밀도 오류로 인해 int가 될 수 있는지 확인하는 데 동의합니다.
Romain Hippeau

1
돈을 사용하려면 1.2가 1.20으로 표시되기를 원할 것입니다. 이는 제안 된 솔루션의 경우에는 해당되지 않습니다. 응시자?
Kjell Rilbe

10
bool IsInteger(double num) {
    if (ceil(num) == num && floor(num) == num)
        return true;
    else
        return false;
}

Problemo solvo.

편집 : 마크 Rushakoff에 의해 Pwned.


4
또는 그냥return ceil(num) == num && floor(num) == num;
Brian Rasmussen

13
또는 단지return ceil(num) == floor(num);
gregsdennis

4

Mark Rushakoff의 답변은 더 간단 할 수 있지만 다음과 같은 작업도 수행되며 암시 적 나누기 작업이 없으므로 더 효율적일 수 있습니다.

     bool isInteger = (double)((int)f) == f ;

     bool isInteger = (decimal)((int)d) == d ;

두 유형 모두에 대해 단일 표현식을 원한다면

     bool isInteger = (double)((int)val) == (double)val ;

4

상한 및 하한이 Int32중요한 경우 :

public bool IsInt32(double value)
{
    return  value >= int.MinValue && value <= int.MaxValue && value == (int)value;
}

첫 번째 테스트, 다음과 같이 캐스팅하면 false를 반환하는 것 이외의 예외가
발생할

@ 컴퓨터, 좋은 지적입니다. 출연과 관련하여 프로젝트 설정에 따라 달라집니다.
nawfal

3
static bool IsWholeNumber(double x) 
{
    return Math.Abs(x % 1) < double.Epsilon;
}

2

이중 유형에 문자열 형식을 사용할 수 있습니다. 예를 들면 다음과 같습니다.

double val = 58.6547;
String.Format("{0:0.##}", val);      
//Output: "58.65"

double val = 58.6;
String.Format("{0:0.##}", val);      
//Output: "58.6"

double val = 58.0;
String.Format("{0:0.##}", val);      
//Output: "58"

도움이되지 않는 경우 알려주십시오.


1
그것은 실제로 값에 분수 부분이 없는지 여부를 결정하는 문제를 다루지 않습니다. 이는 수학적인 질문입니다. 그러나 아마도 그의 설명이 주어지면 OP가 필요로 할 것입니다.
Clifford

2
예, 그는 소수점없이 double 또는 decimal 값을 형식화하려고합니다. 감사합니다 ...
BALKANGraph


0

비슷한 상황에 직면했지만 값이 문자열 인 곳입니다. 사용자는 달러 금액이어야하는 값을 입력하므로 숫자이며 소수점 이하 두 자리까지 있는지 확인하고 싶습니다.

문자열 "s"가 소수점 이하 두 자리 이하의 숫자를 나타내는 경우 true를 반환하고 그렇지 않으면 false를 반환하는 코드가 있습니다. 부동 소수점 값의 부정확성으로 인해 발생하는 문제를 피합니다.

try
{
    // must be numeric value
    double d = double.Parse(s);
    // max of two decimal places
    if (s.IndexOf(".") >= 0)
    {
        if (s.Length > s.IndexOf(".") + 3)
            return false;
    }
    return true;
catch
{
    return false;
}

이에 대해서는 http://progblog10.blogspot.com/2011/04/determining-whether-numeric-value-has.html 에서 자세히 설명 합니다.


4
이것은 당신이 하나의 문화로 일하고 있다고 가정합니다. 예를 들어 1.000,00과 같은 소수를 나타내는 문화권에서는 제대로 작동하지 않습니다.
Jim Geurts

0

int.TryParse를 사용하면 다음과 같은 결과가 나타납니다.

        var shouldBeInt = 3;

        var shouldntBeInt = 3.1415;

        var iDontWantThisToBeInt = 3.000f;

        Console.WriteLine(int.TryParse(shouldBeInt.ToString(), out int parser)); // true

        Console.WriteLine(int.TryParse(shouldntBeInt.ToString(), out parser)); // false

        Console.WriteLine(int.TryParse(iDontWantThisToBeInt.ToString(), out parser)); // true, even if I don't want this to be int

        Console.WriteLine(int.TryParse("3.1415", out  parser)); // false

        Console.WriteLine(int.TryParse("3.0000", out parser)); // false

        Console.WriteLine(int.TryParse("3", out parser)); // true

        Console.ReadKey();

-2

아마도 가장 우아한 해결책은 아니지만 너무 까다 롭지 않으면 효과가 있습니다!

bool IsInteger(double num) {
    return !num.ToString("0.################").Contains(".");
}

8
이것은 끔찍한 해결책입니다
Ospho

-2

'TryParse'메소드를 사용할 수 있습니다.

int.TryParse()

이 값을 정수 정수 값으로 변환 할 수 있는지 확인합니다. 결과는 코드의 다른 곳에서 사용할 수있는 플래그를 나타낼 수 있습니다.


int.TryParse의 인수는 두 배가 아닌 문자열입니다.
Jim Balter

yourDouble.toString("G17")
BackDoorNoBaby

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.