intとfloorにキャストする


120

これらの間に違いはありますか?

float foo1 = (int)(bar / 3.0);
float foo2 = floor(bar / 3.0);

私が理解しているように、どちらの場合も同じ結果になります。コンパイルされたコードに違いはありますか?


1
で少し良くなりますがfloor、これはのためでdoubleはないことに注意してくださいfloat。C99はも持っfloorfていfloatます。
Jens Gustedt、2010

2
したがって、バーが正である限り、同じ結果になります
Zac

1
(注:C ++ではご#include<cmath>利用くださいstd::floor
user202729

タイプはbar何ですか?
chux-モニカを

@chux問題ではありません。3.0で除算すると、とにかく2倍になります
kaalus

回答:


193

intにキャストすると、ゼロに向かって切り捨てられます。 floor()負の無限大に切り捨てられます。bar負の場合、これにより異なる値が得られます。


15
ここの頭に釘を打ったと思います。別の違いfloor()は、意図である場合、の値barが大きすぎてに収まらない場合intです。
Fred Larson

その声明の出典はありますか?
HelloGoodbye 2017年

1
結果が肯定的な場合でも、保証はされません。これこれを見てください。
user202729

27

前に述べたように、正の数の場合は同じですが、負の数の場合は異なります。ルールでは、intは0に向かって丸められ、floorは負の無限大に向かって丸められます。

floor(4.5) = (int)4.5 = 4
floor(-4.5) = -5 
(int)(-4.5) = -4

とはいえ、実行時間にも違いがあります。私のシステムでは、キャストがフロアの3倍以上高速になるように時間を計測しました。

負の数を含む限られた範囲の値のフロア操作を必要とするコードがあります。そして、それは非常に効率的である必要があるため、次の関数を使用します。

int int_floor(double x) 
{ 
    return (int)(x+100000) - 100000; 
}

もちろん、これはxの非常に大きな値(いくつかのオーバーフローの問題が発生します)や-100000未満の負の値の場合などには失敗します。私たちのアプリケーションのために。細かい塩でそれを取り、あなたのシステムでそれをテストする、などですが、私見を検討する価値があります。


「最低でも3倍高速になるようにクロックを設定しました」-> OPはを使用floatしていますが、使用していません。doubleおそらくdoubleアプリケーションでした。Cの場合は、必ずs と併用floorf()してくださいfloat
chux-モニカを

@chux違いがある唯一の理由は、キャストによってコンパイル時の最適化が可能になることです。そのため、その変換は実際には実行中に完全に削除された可能性があります。
ClydeTheGhost 2018年

9

SO 101、他の人があなたの質問に返信した後で質問を変更せず、代わりに新しい質問を書いてください。

なぜ同じ結果になると思いますか?

float foo = (int)(bar / 3.0) //will create an integer then assign it to a float

float foo = fabs(bar / 3.0 ) //will do the absolute value of a float division

bar = 1.0

foo1 = 0;
foo2 = 0.33333...

1
どういう意味fabsですか?質問についてfloorです。0.33333... の床はです0
アーロンフランケ2018年

2
@AaronFranke元の質問が変更されました。8年後には多くのことが起こりそうです;-)他の回答にも同じ前提があることに
注意してください

4

編集:間の混乱のために質問が変更された可能性があるため fabs()とのfloor()です。

元の質問の例の行を考えると:

1.  float foo = (int)(bar / 3.0);

2.  float foo = fabs(bar / 3.0);

違いは、barが負の場合、最初の結果は負、2番目の結果は正になります。1つ目は整数に切り捨てられ、2つ目は小数部を含む完全な10進数値を返します。


3

はい。fabs引数の絶対値を返し、intへのキャストにより除算が切り捨てられます(最も近いintまで)ため、結果はほぼ常に異なります。


2

主な違いは2つあります。

  1. 他の人が指摘したように、整数にキャストするとゼロに向かって切り捨てられますが、floor()常に負の無限大に切り捨てられます。これは、負のオペランドに対する異なる動作です。

  2. まだ(まだ)別の違いを指摘していないようです-引数が以上MAX_INT+1(または未満-MAX_INT-1)の場合、にキャストするintと、最上位ビットが削除される(おそらくC)または未定義の動作( C ++および場合によってはC)。たとえば、int32ビットの場合、符号ビットと31ビットのデータしかありません。したがってdouble、サイズの大きいa でこれを使用すると、意図しない結果が生成されます。


2.a. intオーバーフローへの変換の正確な条件は、引数がINT_MAX+1 以上であることです。対称的に、アンダーフローの条件は、引数がINT_MIN-1以下であることです。
Pascal Cuoq 2014

1
2.b. 浮動小数点から整数への変換のオーバーフローは、C ++では未定義の動作です。「最上位ビットが削除される」ことはありません。を参照してください(ただし、C向けに記述されています):blog.frama-c.com/index.php
post/2013/

0

(int) x の整数部分を保持する要求です x(ここでは丸めはありません)。

fabs(x)= | x | ですので>= 0

例:を(int) -3.5返します-3fabs(-3.5)返す3.5;

一般に fabs (x) >= x、すべてのxに対して。

x >= (int) x もし x >= 0

x < (int) x もし x < 0


x = -3 fabs(-3)= 3(int)-3 = -3; 最後の不平等が成立すると思います。なぜそれが間違っているのか詳しく説明できますか?
Paul Hoang

申し訳ありませんが、私は-3.5を意味しました。-3> -3.5
Dennis Zickefoose

3
最後のステートメントは、x <0 "の場合は依然として" x <= int(x)であり、x <0 "の場合は" x <(int)xではない:負の整数は同じままです。
Tomasz Gandor 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.