OK - saya hampir malu memposting ini di sini (dan saya akan menghapus jika ada orang yang memilih untuk menutup) karena sepertinya pertanyaan mendasar.
Apakah ini cara yang benar untuk mengumpulkan beberapa angka dalam C ++?
Saya tahu ada pertanyaan lain yang terkait dengan ini, tetapi saya secara khusus tertarik untuk mengetahui apa cara terbaik untuk melakukan ini di C ++:
int roundUp(int numToRound, int multiple)
{
if(multiple == 0)
{
return numToRound;
}
int roundDown = ( (int) (numToRound) / multiple) * multiple;
int roundUp = roundDown + multiple;
int roundCalc = roundUp;
return (roundCalc);
}
Pembaruan: Maaf saya mungkin tidak menjelaskan maksudnya. Berikut ini beberapa contohnya:
roundUp(7, 100)
//return 100
roundUp(117, 100)
//return 200
roundUp(477, 100)
//return 500
roundUp(1077, 100)
//return 1100
roundUp(52, 20)
//return 60
roundUp(74, 30)
//return 90
int
.Jawaban:
Ini berfungsi untuk angka positif, tidak yakin tentang negatif. Ini hanya menggunakan bilangan bulat matematika.
Sunting: Ini adalah versi yang berfungsi dengan angka negatif, jika dengan "naik" yang Anda maksud adalah hasil yang selalu> = input.
sumber
if(number<0){ multiple = multiple*(-1); }
di awal untuk membulatkan angka negatif ke arah yang benarif(number<0) multiple = -multiple
lebih mudah.if (remainder == 0)
uji harus mengurus kasus itu. Ini berfungsi untuk saya: ideone.com/Waol7BTanpa syarat:
Ini berfungsi seperti pembulatan dari nol untuk angka negatif
EDIT: Versi yang berfungsi juga untuk angka negatif
Tes
If
multiple
adalah kekuatan 2 (lebih cepat ~ 3,7 kali http://quick-bench.com/sgPEZV9AUDqtx2uujRSa3-eTE80 )Tes
sumber
& ~(x - 1)
sama dengan& -x
aritmatika komplemen dua.Ini berfungsi ketika faktor akan selalu positif:
Sunting: Ini kembali
round_up(0,100)=100
. Silakan lihat komentar Paul di bawah ini untuk solusi yang kembaliround_up(0,100)=0
.sumber
num + factor - 1 - (num + factor - 1) % factor
?num - 1 - (num - 1) % factor + factor
melakukan perhitungan yang sama tanpa risiko integer overflow.Ini adalah generalisasi dari masalah "bagaimana cara mencari tahu berapa banyak byte n bit yang akan diambil? (A: (n bits + 7) / 8).
sumber
(x = roundTo - 1; return (n+x)&~roundTo;)
seperti dalam jawaban saya0xFFF...000
, bukan0xFFF7FFF
atau sesuatu, jadi Anda ingin negasi komplemen 2's (-
: minus) pada kekuatan 2, atau bit-flip pada yang kurang dari kekuatan 2 (invers komplemen satu~
,: tilde bukan minus). Jadi(n+x) & ~x
atau(n-roundTo+1) & -roundTo
.Dan tidak perlu dipusingkan dengan kondisi
sumber
Bagi siapa pun yang mencari jawaban pendek dan manis. Inilah yang saya gunakan. Tidak ada akuntansi untuk negatif.
Itu akan mengembalikan faktor sebelumnya.
Akan kembali berikutnya. Semoga ini bisa membantu seseorang. :)
sumber
Ini berfungsi untuk semua nomor atau basis float (mis. Anda dapat membulatkan -4 ke 6.75 terdekat). Intinya itu mengkonversi ke titik tetap, membulatkan ke sana, lalu mengubahnya kembali. Ini menangani negatif dengan membulatkan AWAY dari 0. Ini juga menangani putaran negatif ke nilai dengan dasarnya mengubah fungsi menjadi roundDown.
Versi int khusus terlihat seperti:
Yang kurang lebih jawaban alas, dengan dukungan input negatif yang ditambahkan.
sumber
double round(double value, double multiple) { double sign = value; multiple = std::copysign(multiple, 1.0); value = std::copysign(value, 1.0); return std::copysign(multiple * std::ceil(value / multiple), sign); }
Atau bertukar ceil untuk mendapatkan pembulatan.Ini adalah pendekatan c ++ modern menggunakan fungsi templat yang berfungsi untuk float, double, long, int dan short (tetapi tidak untuk long, dan long double karena nilai ganda yang digunakan).
Tetapi Anda dapat dengan mudah menambahkan dukungan untuk
long long
danlong double
dengan spesialisasi templat seperti yang ditunjukkan di bawah ini:Untuk membuat fungsi untuk mengumpulkan, gunakan
std::ceil
dan untuk selalu digunakanstd::floor
. Contoh saya dari atas adalah pembulatan menggunakanstd::round
.Buat fungsi templat "bulat" atau lebih dikenal sebagai "plafon bundar" seperti yang ditunjukkan di bawah ini:
Buat fungsi template "bulat ke bawah" atau lebih dikenal sebagai "putaran lantai" seperti yang ditunjukkan di bawah ini:
sumber
long long
danlong double
. Hal yang sama harus dilakukan untuk dua fungsi lainnya.Pertama, kondisi kesalahan Anda (beberapa == 0) mungkin harus memiliki nilai balik. Apa? Saya tidak tahu Mungkin Anda ingin melempar pengecualian, itu terserah Anda. Tapi, mengembalikan tidak ada yang berbahaya.
Kedua, Anda harus memeriksa bahwa numToRound belum banyak. Jika tidak, ketika Anda menambahkan
multiple
untukroundDown
, Anda akan mendapatkan jawaban yang salah.Ketiga, gips Anda salah. Anda
numToRound
memasukkan bilangan bulat, tetapi itu sudah bilangan bulat. Anda perlu melakukan casting untuk menggandakan sebelum divisi, dan kembali ke int setelah multiplikasi.Terakhir, apa yang Anda inginkan untuk angka negatif? Membulatkan "ke atas" dapat berarti membulatkan ke nol (membulatkan ke arah yang sama dengan angka positif), atau menjauh dari nol (angka negatif "lebih besar"). Atau, mungkin Anda tidak peduli.
Ini adalah versi dengan tiga perbaikan pertama, tapi saya tidak berurusan dengan masalah negatif:
sumber
int / int
akan mengembalikan int, yang bukan itu yang kita inginkan.Round to Power of Two:
Untuk berjaga-jaga kalau-kalau ada yang membutuhkan solusi untuk bilangan positif dibulatkan ke kelipatan dua kekuatan terdekat (karena itulah saya berakhir di sini):
Nomor input akan tetap sama jika sudah banyak.
Berikut ini adalah keluaran x86_64 yang diberikan GCC
-O2
atau-Os
(9Sep2013 Build - godbolt GCC online):Setiap baris kode C sangat cocok dengan barisnya dalam rakitan: http://goo.gl/DZigfX
Masing-masing instruksi tersebut sangat cepat , sehingga fungsinya juga sangat cepat. Karena kodenya sangat kecil dan cepat, mungkin berguna untuk
inline
fungsinya saat menggunakannya.Kredit:
sumber
Saya menggunakan:
dan untuk kekuatan dua:
Perhatikan bahwa kedua putaran tersebut bernilai negatif menuju nol (itu berarti bulat hingga tak terhingga positif untuk semua nilai), tidak satu pun dari keduanya bergantung pada limpahan yang ditandatangani (yang tidak ditentukan dalam C / C ++).
Ini memberi:
sumber
n_Align_Up_POT
sejak saya melihatnya di dalam kelas TList Delphi. Ini memiliki batasannya, seperti perataan (banyak) menjadi kekuatan 2, tapi itu jarang menjadi masalah karena saya kebanyakan menggunakannya untuk mendapatkan / memeriksa perataan yang benar untuk SMID. Itu luar biasa dan sepertinya tidak banyak orang tahu tentang itu.Mungkin lebih aman untuk dilemparkan ke float dan menggunakan ceil () - kecuali Anda tahu bahwa divisi int akan menghasilkan hasil yang benar.
sumber
C ++ membulatkan setiap angka ke bawah, jadi jika Anda menambahkan 0,5 (jika 1,5 maka akan menjadi 2) tetapi 1,49 akan menjadi 1,99 karena itu 1.
EDIT - Maaf tidak melihat Anda ingin mengumpulkan, saya sarankan menggunakan metode ceil () alih-alih +0.5
sumber
baik untuk satu hal, karena saya tidak benar-benar mengerti apa yang ingin Anda lakukan, garis
pasti bisa disingkat
sumber
Mungkin ini dapat membantu:
sumber
Untuk selalu mengumpulkan
alwaysRoundUp (1, 10) -> 10
alwaysRoundUp (5, 10) -> 10
alwaysRoundUp (10, 10) -> 10
Selalu bulat
alwaysRoundDown (1, 10) -> 0
alwaysRoundDown (5, 10) -> 0
alwaysRoundDown (10, 10) -> 10
Untuk membulatkannya dengan cara biasa
normalRound (1, 10) -> 0
normalRound (5, 10) -> 10
normalRound (10, 10) -> 10
sumber
Membulatkan ke kelipatan terdekat yang terjadi menjadi kekuatan 2
Ini bisa berguna ketika mengalokasikan bersama bujangan, di mana kenaikan pembulatan yang Anda inginkan adalah kekuatan dua, tetapi nilai yang dihasilkan hanya perlu kelipatannya. Pada
gcc
tubuh fungsi ini menghasilkan 8 instruksi perakitan tanpa divisi atau cabang.sumber
Saya menemukan algoritma yang agak mirip dengan yang diposting di atas:
int [(| x | + n-1) / n] * [(nx) / | x |], di mana x adalah nilai input pengguna dan n adalah multiple yang digunakan.
Ia bekerja untuk semua nilai x, di mana x adalah bilangan bulat (positif atau negatif, termasuk nol). Saya menulisnya secara khusus untuk program C ++, tetapi ini pada dasarnya dapat diimplementasikan dalam bahasa apa pun.
sumber
Untuk numToRound negatif:
Seharusnya sangat mudah untuk melakukan ini tetapi modulo% operator standar tidak menangani angka negatif seperti yang mungkin diharapkan. Misalnya -14% 12 = -2 dan bukan 10. Hal pertama yang harus dilakukan adalah mendapatkan operator modulo yang tidak pernah mengembalikan angka negatif. Maka roundUp sangat sederhana.
sumber
Inilah yang akan saya lakukan:
Kode mungkin tidak optimal, tapi saya lebih suka kode bersih daripada kinerja kering
sumber
int
untukfloat
siap kehilangan presisi dan membuat jawaban yang salah.meskipun:
akan menyarankan menggunakan bilangan bulat yang tidak ditandatangani sebagai gantinya, yang telah mendefinisikan perilaku overflow.
Anda akan mendapatkan pengecualian beberapa == 0, tapi itu bukan masalah yang didefinisikan dengan baik dalam kasus itu.
sumber
c:
dan untuk ~ / .bashrc Anda:
sumber
Saya menggunakan kombinasi modulus untuk membatalkan penambahan sisanya jika
x
sudah beberapa:Kami menemukan kebalikan dari sisanya kemudian modulus dengan pembagi lagi untuk membatalkannya jika pembagi itu sendiri kemudian tambahkan
x
.sumber
Inilah solusi saya berdasarkan saran OP, dan contoh-contoh yang diberikan oleh orang lain. Karena sebagian besar semua orang mencarinya untuk menangani angka negatif, solusi ini tidak hanya itu, tanpa menggunakan fungsi khusus, yaitu abs, dan sejenisnya.
Dengan menghindari modulus dan sebagai gantinya menggunakan pembagian, angka negatif adalah hasil alami, meskipun dibulatkan ke bawah. Setelah versi dibulatkan dihitung, maka diperlukan matematika untuk mengumpulkan, baik dalam arah negatif atau positif.
Perhatikan juga bahwa tidak ada fungsi khusus yang digunakan untuk menghitung apa pun, sehingga ada peningkatan kecepatan kecil di sana.
sumber
RoundUp(INT_MIN, -1)
apan / multiple
yangint
meluap.Saya pikir ini akan membantu Anda. Saya telah menulis program di bawah ini dalam C.
sumber
sumber
Ini mendapatkan hasil yang Anda cari untuk bilangan bulat positif:
Dan inilah outputnya:
sumber
Saya pikir ini bekerja:
sumber
Ini bekerja untuk saya tetapi tidak mencoba untuk menangani yang negatif
sumber
Berikut ini adalah solusi super sederhana untuk menunjukkan konsep keanggunan. Ini pada dasarnya untuk terkunci jaringan.
(kode semu)
sumber