decimal / doubleが整数かどうかを判断する方法は?


225

10進数値または2進数値が整数かどうかを確認するにはどうすればよいですか?

例えば:

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
これは、数値が整数で始まる場合に機能しますが、必ずしも数値が何らかの浮動小数点計算の結果である場合には機能しません。「(d%1)<イプシロン」のように、epsionが小さな値である場合はどうでしょうか。
エイドリアンロペス2010年

9
このスレッドでの最良の回答が、受け入れられた回答ではなくコメントであるのは残念です。素敵なエイドリアン。
starskythehutch

13
上記のエイドリアンのコメントも最良の答えだと思います。彼のアドバイスを正式なC#コードに入れるには:if(Math.Abs​​(n%1)<Double.Epsilon){// nが整数の場合は何かを行います}
ルーベンラミレスパドロン2015年

7
IMHO、モジュラス演算子と浮動小数点数は、有用な方法で混合されません。提案されたコードは、使用されるキーストロークの数を考えると非常に混乱し、.NET言語以外ではほとんど機能しません。また、正しい方法よりもはるかに遅いと思います(除算をまったく使用しません)。これを行う正しい方法は、Math.Abs(d-(int)d) < double.Epsilonです。私たち全員が大学での最初のプログラミングクラスの最初の週に学んだはずです。
krowe2

9
実際、質問が述べられているように、この答えは正しいですし、コメントは間違っています。OPは、doubleが整数であるかどうかを数学的な目的で知りたいのではなく、それを表示する方法を知りたいと考えています。正確な整数値のみが小数点なしで表示されます。また、浮動小数点ではmodが役に立たず、.NETの外部で機能しないことについてのコメントも十分に説明されていません。そして(int)d、ほとんどのdouble値に対して例外をスローする災害です。
ジムバルター2016年

49

これを行う方法はいくつもあります。例えば:

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

モジュロを使用することもできます。

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

これらの1つは他よりも高速でしょうか?パフォーマンスに敏感な状況でこれを実行したいと考えています。
バジル

@Basil-状況によって異なります。あなた自身のためにいくつかのタイミングを行い、判断する必要があります。
Erik Funkenbusch 2013

4
Math.Abs(d-(int)d) < double.Epsilonより安全d == (int)d
Reactgular 2014年

3
@MathewFoscarini-私はあなたが混乱していると思います。16.1〜6.1の結果はintではないため、これをfalseに設定します。ポイントは、与えられた値がintであるかどうかを見つけることであり、およそintである何かがintであるかどうかではありません。
エリックファンケンブッシュ2014年

1
@MathewFoscarini-はい、intは10進数値(または10進数値0)のない数値です。16.1-6.1は0の10進値を作成しません。これは、IEEE浮動小数点形式の癖によって引き起こされる非常に小さい非ゼロの値です。数値が10進数の値を持つようにサポートされているかどうかを知る方法はないため、丸め値を想定することも同様に不正確です。質問の目的は、浮動小数点数が整数であるかどうかを知ることであり、ほぼ整数であるかどうかを知ることではありませんでした。
エリックファンケンブッシュ2014年

21

これはどう?

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

の同じコードdecimal

マーク・バイアーズは実際に良い点を作りました:これはあなたが本当に望んでいることではないかもしれません。何をした場合、本当に気にしている数が最も近い2桁まで四捨五入するかどうかの整数であり、、あなたの代わりにこれを行うことができます:

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

1
おそらくあなたのソリューションを更新して追加してください:&& number <int.MaxValue && number> int.MinValue
Walter Vehoeven '20

12

提案された解決策は単純な例で機能するように見えますが、これを一般的に行うことは悪い考えです。数値は正確には整数ではない可能性がありますが、フォーマットしようとすると、取得する整数に十分近くなります1.000000ます。これは、理論的には正確に1を与えるはずの計算を行った場合に発生する可能性がありますが、実際には、丸め誤差のために、1に非常に近いが正確には等しくない数値が得られます。

代わりに、最初にフォーマットし、文字列がピリオドで終了し、その後にゼロが続く場合は、それらを削除します。末尾のゼロを自動的に削除するために使用できるいくつかの形式もあります。これはあなたの目的には十分かもしれません。

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

出力:

1
1.02

@Markは面白いですね。末尾のゼロを取り除くフォーマットの例はありますか?
Jim Geurts、2010年

それはより安全であり、OPがおそらく何をすべきかについて同意しますが、値が小数部分を持っているかどうかというより狭い(しかしより興味深い)質問に対する答えではありません。
2010年

3
@Clifford:私は通常、タイトルが何を言っているかに基づいてではなく、OPの問題を解決するのに最適なものに基づいて回答しようとします。タイトルが問題の正確な説明になることはほとんどありません。
マークバイアーズ

+1 floatまたはdoubleをテストして、それらがintである可能性があるかどうかを確認しようとすると、丸めと精度のエラーのために悪いことに同意します。
Romain Hippeau、

1
お金の使い方については、1.2を1.20として表示することをお勧めしますが、これは推奨されるソリューションの場合とは異なります。テイカーはいますか?
Kjell Rilbe、2014

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

問題ソルボ。

編集:マーク・ルシャコフによって犯された。


4
またはただreturn ceil(num) == num && floor(num) == num;
ブライアンラスムッセン

13
または単にreturn ceil(num) == floor(num);
gregsdennis 2013年

4

マーク・ルシャコフの答えはより単純かもしれませんが、以下も機能し、暗黙の除算演算がないのでより効率的かもしれません:

     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を返す以外の例外がスローされ、おそらく回答が更新されます
Walter Vehoeven

@コンピュータ、そうですね。キャストで投げるということについては、プロジェクトの設定に依存すると思います。
nawfal


2

double型には文字列フォーマットを使用できます。次に例を示します。

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が彼の説明的なメモを与えて必要とするものです。
クリフォード

2
はい、小数点なしでdoubleまたはdecimal値をフォーマットするだけです。ありがとう...
2010年


0

私も同じような状況に直面しましたが、値は文字列です。ユーザーは金額と思われる値を入力するので、それが数値であり、小数点以下2桁以下であることを検証したいと思います。

文字列 "s"が小数点以下2桁の数値を表す場合は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つの文化で作業していることを前提としています。例えば、それは1.000,00のような小数を表す文化で正しく動作しません
ジム・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の引数は、doubleではなく文字列です。
ジムバルター2016年

yourDouble.toString("G17")
BackDoorNoBaby

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.