float
変数に整数値が含まれているかどうかを確認するにはどうすればよいですか?これまでのところ、私は使用しています:
float f = 4.5886;
if (f-(int)f == 0)
printf("yes\n");
else printf("no\n");
しかし、より良い解決策があるのか、それとも何らかの(または多くの)欠点があるのか疑問に思います。
既に与えられたすばらしい答えとは別に、ceilf(f) == f
またはfloorf(f) == f
を使用することもできます。 true
が整数の場合、両方の式はf
を返します。また、Returnfalse
はNaN( NaNは常に等しくない )およびtrue
は±∞であり、切り捨てられた結果を保持するために使用される整数型のオーバーフローに関する問題はありませんfloorf()
/ceilf()
がfloat
sを返すため。
ここでのテクニックのほとんどは、事前の計算による丸め誤差は要因ではないと仮定して有効であることに留意してください。例えば。 youcould次のようにroundf
を使用します:
_float z = 1.0f;
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
_
これや他の同様の手法(ceilf
、long
へのキャストなど)の問題は、整数定数に対してはうまく機能するが、数値が浮動小数点の丸め誤差の影響を受けた計算の結果。例えば:
_float z = powf(powf(3.0f, 0.05f), 20.0f);
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
_
(31/20)20 実際の計算結果は2.9999992847442626953125であるため、3に等しくなければなりません。
fmodf
またはその他の同様の方法は、この対象となります。複雑な計算または丸めがちな計算を実行するアプリケーションでは、通常、「全体数」を構成するものの「許容値」を定義します(これは一般に浮動小数点の等値比較に使用されます)。この許容値epsilonとよく呼ばれます。たとえば、コンピューターに最大+/- 0.00001の丸め誤差を許すとしましょう。次に、z
をテストしている場合、0.00001のイプシロンを選択して実行できます。
_if (fabsf(roundf(z) - z) <= 0.00001f) {
printf("integer\n");
} else {
printf("fraction\n");
}
_
ここでceilf
を使用したくないのは、たとえばceilf(1.0000001)
は1ではなく2であり、ceilf(-1.99999999)
は-2ではなく-1です。
rintf
の代わりにroundf
を使用することもできます。
アプリケーションに適した許容値を選択します(そして、はい、場合によっては許容値ゼロが適切です)。詳細については、この記事の 浮動小数点数の比較 をご覧ください。
stdlib float modf(float x、float * ipart)は2つの部分に分割され、戻り値(小数部分)== 0かどうかを確認します。
if (fmod(f, 1) == 0.0) {
...
}
math.h
およびlibm
。
if (f <= LONG_MIN || f >= LONG_MAX || f == (long)f) /* it's an integer */
100%確信はありませんが、fをintにキャストし、fからそれを引くと、floatにキャストし直されていると思います。この場合、これはおそらく問題になりませんが、何らかの理由でintであると予想している場合は、将来的に問題が発生する可能性があります。
それ自体がより良い解決策であるかどうかはわかりませんが、代わりにモジュラスの数学を使用することができます、例えば:float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true;
暗黙のキャストが作用します。このコードでは、bool isIntは、小数点の右側がすべてゼロの場合はtrue、そうでない場合はfalseである必要があります。
#define twop22 (0x1.0p+22)
#define ABS(x) (fabs(x))
#define isFloatInteger(x) ((ABS(x) >= twop22) || (((ABS(x) + twop22) - twop22) == ABS(x)))