当前位置:网站首页>Round up a little detail of the round
Round up a little detail of the round
2022-04-23 06:37:00 【mightbxg】
Rounding is to get the nearest integer to a floating-point number , So-called “ rounding ” It means round .C++ Can be called std::round To achieve . It looks like a simple operation, isn't it , In fact, there are some small details .
std::round Cannot evaluate... During compilation
Compile time (compile-time) Calculation and operation period (run-time) The concept of calculation must be understood by everyone , If a function can calculate the result during compilation ( Such functions are called constant expression functions constexpr funciton), That can save the calculation time during the operation period . In some cases, it must be required to calculate... At compile time , For example, template parameters :
template <int N>
void printN() {
std::cout << N << '\n'; }
int main()
{
constexpr int n = std::round(0.5);
printN<n>();
}
The above code is in MSVC and Clang Cannot be compiled in , because std::round Cannot calculate at compile time ! It sounds incredible , Why such a simple function can only be calculated at run time ?
The answer is Error handling , When rounding fails ( Rounding result is out of integer range ) when ,std::round Store the error information in the global variable ( It's actually thread-local, That is, it can be regarded as global in a single thread , For thread safety ) math_errhandling in , So that developers can check whether there are errors .
Obviously, such an error handling mechanism is executed during operation . Like rounding ,std cmath All the mathematical functions in... Are used math_errhandling, Therefore, it cannot be calculated during compilation .
But here's the thing ,GCC Be able to calculate... During compilation std Mathematical functions , So the above code can use GCC Normal compile run . but C++ standard (c++draft) It's clear :
An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required.
In plain English : The function that is not said to be a constant expression in the standard library has been changed to a constant expression ! therefore GCC It's self assertion . For program compatibility , Try not to take advantage of GCC This feature is better .
Rounding may be slow
If you really care about computing speed ,std::round It may not be a good choice , The same reason is Error handling .
One side , Error handling itself can lead to additional time consumption ( Error judgment and error information are written to global variables ). On the other hand ,math_errhandling The existence of this global variable leads to std::round Vectorization is not possible ( The compiler will automatically vectorize and accelerate some calculations ).
If you want to get the ultimate computing speed , At the same time, it can ensure that the rounding result will not overflow , You can realize a rounding without error handling by yourself :
inline static int myRound(double val)
{
return (int)(val + (val >= 0 ? 0.5 : -0.5));
}
Or make use of SSE Instructions , It should be faster :
inline static int myRound(double val)
{
__m128d t = _mm_set_sd(val);
return _mm_cvtsd_si32(t);
}
( In fact, the above two implementations come from OpenCV Of cvRound).
Rounding is not necessarily “ Five in ”
If you use OpenCV, Will find 1.5 and 2.5 adopt cvRound After rounding, it's all 2, The agreed rounding ?
This is because ,cvRound Give priority to SSE Realization , and SSE The rounding in is bankers’ rounding Strategy ( also called statistician’s rounding、Gaussian rounding), This strategy will x.5 Round to the nearest even numbers (round half to even), In order to solve the problem of high results caused by rounding in Statistics .
By default (FE_TONEAREST) Next ,std::round It's round off ,std::rint yes bankers’ rounding.
版权声明
本文为[mightbxg]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230546583775.html
边栏推荐
猜你喜欢
随机推荐
[ThreadX] h743 + ThreadX + Filex migration record
ArcGIS license错误-15解决方法
Object array and object pointer
[ThreadX] h743zi + lan8720 + ThreadX + netx duo transplantation
1007 go running (hdu6808) in the fourth game of 2020 Hangzhou Electric Multi school competition
The onnx model of yolov5 removes the transfer layer
类和对象的初始化(构造函数与析构函数)
相机标定:关键点法 vs 直接法
对象数组与对象指针
C语言的浪漫
grub boot. S code analysis
如何安装jsonpath包
1006 finding a mex (hdu6756)
MySQL groups are sorted by a field, and the first value is taken
用二进制进行权限管理
Cross domain issues - allow origin header contains multiple values but only one is allowed
Cf6d lizards and fundamentals 2 problem solving
数组旋转
实现一个计算m~n(m<n)之间所有整数的和的简单函数
圆整 round 的一点点小细节









