มาตรฐาน C ++ 03 อาศัยมาตรฐาน C90 สำหรับสิ่งที่มาตรฐานเรียกว่าไลบรารี C มาตรฐานซึ่งครอบคลุมในร่างมาตรฐาน C ++ 03 ( มาตรฐานร่างสาธารณะที่ใกล้เคียงที่สุดกับ C ++ 03 คือ N1804 ) ส่วน1.2
อ้างอิงเชิงบรรทัด :
ไลบรารีที่อธิบายไว้ในข้อ 7 ของ ISO / IEC 9899: 1990 และข้อ 7 ของ ISO / IEC 9899 / Amd.1: 1995 ต่อไปนี้จะเรียกว่า Standard C Library 1)
ถ้าเราไปที่เอกสาร C สำหรับรอบ lround, llround บน cppreferenceเราจะเห็นว่ารอบและฟังก์ชันที่เกี่ยวข้องนั้นเป็นส่วนหนึ่งของC99และจะไม่สามารถใช้ได้ใน C ++ 03 หรือก่อนหน้า
ใน C ++ 11 การเปลี่ยนแปลงนี้นับตั้งแต่ C ++ 11 อาศัยมาตรฐาน C99 ฉบับร่างสำหรับไลบรารีมาตรฐาน Cดังนั้นจึงจัดเตรียมstd :: round และสำหรับประเภทคืนที่ครบถ้วน 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 ;
}
ตัวเลือกอื่นจาก C99 จะเป็นstd :: truncซึ่ง:
คำนวณจำนวนเต็มที่ใกล้ที่สุดไม่มากกว่าขนาด 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 ;
}
หากคุณต้องการที่จะสนับสนุนไม่ใช่ C ++ 11 การใช้งานทางออกที่ดีที่สุดของคุณจะใช้รอบส่งเสริม iRound, lround, llroundหรือเพิ่ม TRUNC
การกลิ้งเวอร์ชั่นรอบของคุณเองนั้นยาก
กลิ้งของคุณเองอาจจะไม่คุ้มค่าความพยายามเป็นหนักกว่ามันก็ดู: ปัดเศษลอยตัวเต็มที่ใกล้เคียงที่สุดส่วนที่ 1 , ปัดเศษลอยตัวเต็มที่ใกล้เคียงที่สุดส่วนที่ 2และปัดเศษลอยตัวเต็มที่ใกล้เคียงที่สุด, ส่วน 3อธิบาย:
ตัวอย่างเช่นการใช้งานทั่วไปของคุณโดยใช้std::floor
และการเพิ่ม0.5
ไม่ทำงานสำหรับอินพุตทั้งหมด:
double myround(double d)
{
return std::floor(d + 0.5);
}
หนึ่งอินพุตที่จะล้มเหลวสำหรับคือ0.49999999999999994
( ดูสด )
การใช้งานทั่วไปอื่น ๆ เกี่ยวข้องกับการคัดเลือกประเภทจุดลอยตัวเป็นประเภทอินทิกรัลซึ่งสามารถเรียกใช้พฤติกรรมที่ไม่ได้กำหนดในกรณีที่ส่วนอินทิกรัลไม่สามารถแสดงในประเภทปลายทางได้ เราสามารถเห็นสิ่งนี้ได้จากร่างมาตรฐาน C ++ ส่วน4.9
การแปลงแบบอินทิกรัลแบบลอยตัวซึ่งกล่าวว่า (การเน้นที่เหมือง ):
prvalue ของชนิด floating point สามารถแปลงเป็น prvalue ของชนิดจำนวนเต็ม การแปลงตัดทอน นั่นคือส่วนที่เป็นเศษส่วนจะถูกยกเลิก พฤติกรรมจะไม่ได้กำหนดถ้าค่าที่ถูกตัดทอนไม่สามารถแสดงในประเภทปลายทาง [ ... ]
ตัวอย่างเช่น:
float myround(float f)
{
return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}
ป.ร. ให้ไว้std::numeric_limits<unsigned int>::max()
เป็น4294967295
แล้วโทรต่อไปนี้:
myround( 4294967296.5f )
จะทำให้เกิดการล้น ( ดูสด )
เราสามารถเห็นความยากลำบากนี้จริงๆโดยดูที่คำตอบนี้เพื่อกระชับวิธีการใช้รอบ () ใน C? ซึ่งอ้างอิงรุ่นnewlibsของความแม่นยำรอบลอยเดี่ยว มันเป็นฟังก์ชั่นที่ยาวมาก ๆ สำหรับบางสิ่งที่ดูเรียบง่าย ดูเหมือนว่าไม่น่าเป็นไปได้ที่ทุกคนที่ไม่มีความรู้อย่างลึกซึ้งเกี่ยวกับการใช้งานจุดลอยตัวสามารถใช้ฟังก์ชันนี้ได้อย่างถูกต้อง:
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;
}
ในทางกลับกันหากไม่มีวิธีการแก้ปัญหาอื่นใดnewlib ที่ใช้งานได้อาจเป็นตัวเลือกเนื่องจากเป็นการใช้งานที่ผ่านการทดสอบอย่างดี
std::cout << std::fixed << std::setprecision(0) << -0.9
เช่น