Transmisikan ke int vs floor

120

Apakah ada perbedaan antara ini:

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

Seperti yang saya pahami, kedua kasus memiliki hasil yang sama. Apakah ada perbedaan dalam kode yang dikompilasi?

OgreSwamp
sumber
1
sedikit lebih baik dengan floor, tetapi berhati-hatilah karena ini doublebukan untuk float. C99 juga memiliki floorfuntuk float.
Jens Gustedt
2
Jadi mereka memiliki hasil yang sama selama barnya positif
Zac
1
(catatan: dalam C ++ harap #include<cmath>dan gunakan std::floor)
pengguna202729
Jenis apakah bar?
chux - Pulihkan Monica
@chux Tidak masalah, bagi dengan 3.0 akan membuatnya menjadi dua kali lipat
kaalus

Jawaban:

194

Mentransmisikan ke int akan dipotong ke arah nol. floor()akan memotong ke arah negatif tak hingga. Ini akan memberi Anda nilai yang berbeda jika barnegatif.

James Curran
sumber
15
Saya pikir Anda tepat sasaran di sini. Perbedaan lain, jika floor()maksudnya, adalah jika nilai barterlalu besar untuk muat int.
Fred Larson
Apakah Anda punya sumber untuk pernyataan itu?
HelloGoodbye
1
Meskipun hasilnya positif, itu tidak dijamin. Lihat ini dan ini .
pengguna202729
27

Seperti yang telah dikatakan sebelumnya, untuk bilangan positif mereka sama, tetapi berbeda untuk bilangan negatif. Aturannya adalah int membulatkan menuju 0, sedangkan floor membulatkan menuju negatif tak terhingga.

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

Dengan demikian, ada juga perbedaan waktu eksekusi. Di sistem saya, saya menghitung waktu casting setidaknya 3 kali lebih cepat dari floor.

Saya memiliki kode yang memerlukan pengoperasian lantai dengan kisaran nilai yang terbatas, termasuk angka negatif. Dan itu harus sangat efisien, jadi kami menggunakan fungsi berikut untuk itu:

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

Tentu saja ini akan gagal untuk nilai x yang sangat besar (Anda akan mengalami beberapa masalah luapan) dan untuk nilai negatif di bawah -100000, dll. Tapi saya telah mencatatnya setidaknya 3 kali lebih cepat dari lantai, yang sangat penting untuk aplikasi kita. Ambillah dengan sebutir garam, uji pada sistem Anda, dll. Tetapi ada baiknya mempertimbangkan IMHO.

brice rebsamen
sumber
"Saya telah mencatatnya setidaknya 3 kali lebih cepat dari lantai" -> OP yang digunakan float, bukan double- mungkin doubleaplikasi Anda. Jika di C, pastikan untuk menggunakan floorf()dengan floats.
chux
@chux Saya pikir satu-satunya alasan ada perbedaan adalah bahwa pemeran memungkinkan pengoptimalan waktu kompilasi. Sehingga konversi itu mungkin benar-benar telah dihapus seluruhnya selama eksekusi.
ClydeTheGhost
9

SO 101, jangan ubah pertanyaan Anda setelah orang menjawab pertanyaan Anda, melainkan tulis pertanyaan baru.

Menurut Anda, mengapa mereka akan mendapatkan hasil yang sama?

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...
AndersK
sumber
1
Apa yang Anda maksud dengan fabs? Pertanyaannya tentang floor. Lantai 0.33333... adalah 0.
Aaron Franke
2
@AaronFranke pertanyaan asli telah diubah. tampaknya banyak yang bisa terjadi dalam 8 tahun ;-) perhatikan jawaban lain memiliki premis yang sama
AndersK
4

EDIT: Karena pertanyaan mungkin telah diubah karena kebingungan antara fabs()dan floor().

Diberikan baris contoh pertanyaan asli:

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

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

Perbedaannya adalah jika batang negatif, hasilnya akan negatif dengan yang pertama tetapi positif dengan yang kedua. Yang pertama akan dipotong menjadi integer dan yang kedua akan mengembalikan nilai desimal penuh termasuk bagian pecahan.

Amardeep AC9MF
sumber
3

Iya. fabsmengembalikan nilai absolut dari argumennya, dan cast ke int menyebabkan pemotongan divisi (turun ke int terdekat), sehingga hasilnya hampir selalu berbeda.

warrenm
sumber
2

Ada dua perbedaan utama:

  1. Seperti yang telah ditunjukkan orang lain, casting ke integer akan dipotong ke nol, sedangkan floor()akan selalu dipotong ke arah negatif tak terhingga; ini adalah perilaku yang berbeda untuk operan negatif.

  2. Tidak ada seorang pun (belum) yang menunjukkan perbedaan lain - jika argumen Anda lebih besar dari atau sama dengan MAX_INT+1(atau kurang dari -MAX_INT-1) maka mentransmisikan ke intbit paling atas akan dijatuhkan (C, mungkin) atau perilaku tidak terdefinisi ( C ++ dan mungkin C). Misalnya jika Anda int32 bit, Anda hanya akan memiliki bit tanda ditambah 31 bit data. Jadi menggunakan ini dengan doubleyang berukuran besar akan menghasilkan hasil yang tidak diinginkan.

abligh
sumber
2.a. Kondisi yang tepat untuk konversi menjadi intmeluap adalah argumennya lebih besar atau sama dengan INT_MAX+1. Secara simetris, kondisi underflow adalah argumennya lebih rendah atau sama dengan INT_MIN-1.
Pascal Cuoq
1
2.b. Overflow dalam konversi dari floating-point ke integer adalah perilaku yang tidak ditentukan dalam C ++. Ini tidak “menghasilkan bit paling atas yang dibuang”. Lihat (meskipun ditulis untuk C): blog.frama-c.com/index.php?post/2013/10/09/…
Pascal Cuoq
0

(int) xadalah permintaan untuk mempertahankan bagian integer x(tidak ada pembulatan di sini)

fabs(x)= | x | jadi itu >= 0;

Mis: (int) -3.5kembali -3; fabs(-3.5)kembali 3.5;

Secara umum, fabs (x) >= xuntuk semua x;

x >= (int) x jika x >= 0

x < (int) x jika x < 0

Paul Hoang
sumber
x = -3 fabs (-3) = 3 (int) -3 = -3; Saya pikir ketidaksetaraan terakhir terjadi. Bisakah Anda menjelaskan lebih lanjut mengapa itu salah?
Paul Hoang
Maaf, maksud saya -3,5, contoh yang Anda berikan. -3> -3.5
Dennis Zickefoose
3
Pernyataan terakhir tetap harus "x <= int (x) if x <0", dan bukan "x <(int) x if x <0": bilangan bulat negatif tetap sama.
Tomasz Gandor