Standar C ++ 03 bergantung pada standar C90 untuk apa yang standar sebut Perpustakaan C Standar yang tercakup dalam konsep standar C ++ 03 ( standar konsep terdekat yang tersedia untuk publik dengan C ++ 03 adalah N1804 ) bagian 1.2
Referensi normatif :
Perpustakaan yang dijelaskan dalam ayat 7 ISO / IEC 9899: 1990 dan ayat 7 ISO / IEC 9899 / Amd.1: 1995 selanjutnya disebut Perpustakaan Standar C. 1)
Jika kita pergi ke dokumentasi C untuk round, lround, llround pada cppreference kita dapat melihat bahwa round dan fungsi terkait adalah bagian dari C99 dan karenanya tidak akan tersedia di C ++ 03 atau sebelumnya.
Dalam C ++ 11 perubahan ini karena C ++ 11 bergantung pada standar draft C99 untuk pustaka standar C dan karenanya menyediakan std :: round dan untuk tipe pengembalian integral std :: lround, std :: llround :
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::round( 0.4 ) << " " << std::lround( 0.4 ) << " " << std::llround( 0.4 ) << std::endl ;
std::cout << std::round( 0.5 ) << " " << std::lround( 0.5 ) << " " << std::llround( 0.5 ) << std::endl ;
std::cout << std::round( 0.6 ) << " " << std::lround( 0.6 ) << " " << std::llround( 0.6 ) << std::endl ;
}
Pilihan lain juga dari C99 adalah std :: trunc yang:
Menghitung bilangan bulat terdekat tidak lebih besar dari pada arg.
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::trunc( 0.4 ) << std::endl ;
std::cout << std::trunc( 0.9 ) << std::endl ;
std::cout << std::trunc( 1.1 ) << std::endl ;
}
Jika Anda perlu mendukung aplikasi non C ++ 11, taruhan terbaik Anda adalah menggunakan boost round, iround, lround, llround atau boost trunc .
Memutar versi putaran Anda sendiri itu sulit
Menggulung sendiri mungkin tidak sepadan dengan usaha yang lebih sulit daripada yang terlihat: membulatkan float ke integer terdekat, bagian 1 , Rounding float ke integer terdekat, bagian 2 dan Rounding float ke integer terdekat, bagian 3 menjelaskan:
Misalnya, roll yang umum digunakan std::floor
dan ditambahkan oleh implementasi Anda 0.5
tidak berfungsi untuk semua input:
double myround(double d)
{
return std::floor(d + 0.5);
}
Satu input yang gagal adalah 0.49999999999999994
, ( lihat langsung ).
Implementasi umum lainnya melibatkan casting tipe floating point ke tipe integral, yang dapat memicu perilaku tidak terdefinisi dalam kasus di mana bagian integral tidak dapat diwakili dalam tipe tujuan. Kita dapat melihat ini dari konsep C ++ bagian standar 4.9
Konversi integral-mengambang yang mengatakan ( penekanan milikku ):
Nilai awal dari tipe floating point dapat dikonversi ke nilai awal dari tipe integer. Konversi terpotong; yaitu, bagian pecahan dibuang. Perilaku tidak terdefinisi jika nilai terpotong tidak dapat diwakili dalam tipe tujuan. [...]
Sebagai contoh:
float myround(float f)
{
return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}
Mengingat std::numeric_limits<unsigned int>::max()
adalah 4294967295
maka panggilan berikut:
myround( 4294967296.5f )
akan menyebabkan overflow, ( lihat langsung ).
Kita dapat melihat betapa sulitnya ini sebenarnya dengan melihat jawaban ini untuk cara ringkas untuk mengimplementasikan round () di C? yang mereferensikan versi newlibs dari putaran float presisi tunggal. Ini adalah fungsi yang sangat panjang untuk sesuatu yang tampaknya sederhana. Tampaknya tidak mungkin bahwa siapa pun tanpa pengetahuan mendalam tentang implementasi floating point dapat dengan benar mengimplementasikan fungsi ini:
float roundf(x)
{
int signbit;
__uint32_t w;
/* Most significant word, least significant word. */
int exponent_less_127;
GET_FLOAT_WORD(w, x);
/* Extract sign bit. */
signbit = w & 0x80000000;
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23)
{
if (exponent_less_127 < 0)
{
w &= 0x80000000;
if (exponent_less_127 == -1)
/* Result is +1.0 or -1.0. */
w |= ((__uint32_t)127 << 23);
}
else
{
unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0)
/* x has an integral value. */
return x;
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
}
else
{
if (exponent_less_127 == 128)
/* x is NaN or infinite. */
return x + x;
else
return x;
}
SET_FLOAT_WORD(x, w);
return x;
}
Di sisi lain, jika tidak ada solusi lain yang dapat digunakan, newlib berpotensi menjadi pilihan karena merupakan implementasi yang teruji dengan baik.
std::cout << std::fixed << std::setprecision(0) << -0.9
, misalnya.