问题
Hi i want to round double numbers like this (away from zero) in C++:
4.2 ----> 5
5.7 ----> 6
-7.8 ----> -8
-34.2 ----> -35
What is the efficient way to do this?
回答1:
inline double myround(double x)
{
return x < 0 ? floor(x) : ceil(x);
}
As mentioned in the article Huppie cites, this is best expressed as a template that works across all float types
See http://en.cppreference.com/w/cpp/numeric/math/floor and http://en.cppreference.com/w/cpp/numeric/math/floor
or, thanks to Pax, a non-function version:
x = (x < 0) ? floor(x) : ceil(x);
回答2:
There is a nice article about a similar problem on CPlusPlus.com. The easy solution to your problem should be something like this:
double customRound( double value ) const {
return value < 0 ? floor( value ) : ceil( value );
}
A better solution is the one mentioned in the article, which uses a template:
//--------------------------------------------------------------------------
// symmetric round up
// Bias: away from zero
template <typename FloatType>
FloatType ceil0( const FloatType& value )
{
FloatType result = std::ceil( std::fabs( value ) );
return (value < 0.0) ? -result : result;
}
回答3:
The x < 0 ? floor(x) : ceil(x);
approach of Ruben Bartelink is good. Yet consider what happens with special cases of x = -0.0
, x = NaN
.
Rather than have myround(-0.0)
potentially return +0.0
1 and have myround(NaN)
return with a changed payload of the NaN
, consider the below.
myround_alt(-0.0)
returns -0.0
.
myround_alt(NaN)
more likely returns an unchanged payload NaN. Not-a-number stuff is tricky and not well defined. IAC, it is the myround_alt(-0.0)
--> -0.0
I am seeking.
inline double myround_alt(double x) {
if (x > 0) return ceil(x);
if (x < 0) return floor(x);
return x;
}
1IEC 60559 floating-point arithmetic specifies ceil(±0)
returns ±0
so this approach not needed with implementations that strictly follow that spec. Yet many C floating point implementation do not follow that (C does not require it) or fail in such comer cases like this.
回答4:
try
double rounded = _copysign(ceil(abs(x)), x);
回答5:
This will work, and it does not even require math.h
, or any libraries. I took a distinct approach to achieve the wanted functionality. Flooring negative numbers and ceiling positive numbers is just one way to do it. It does the same thing as truncating the number, and increasing the absolute value by one, If it is not already an integer. Like this:
inline double InvertedTrunc(double Number) {
return (Number == (int)Number ? Number : ((int)Number)+(Number < 0 ? -1 : 1)); //casting to int truncates it
} //Though be aware of overflow, not recommended for large numbers
Though something to be aware of is overflow, so this is not recommended for larger numbers.
来源:https://stackoverflow.com/questions/1326510/c-rounding-of-numbers-away-from-zero