Double Decimal Rounding in C++ [duplicate] - c++

I'm trying to allow my program to round a number up and down respectively.
For example, if the number is 3.6, my program is suppose to round up the nearest number which is 4 and if the number is 3.4, it will be rounded down to 3.
I tried using the ceil library to get the average of 3 items.
results = ceil((marks1 + marks2 + marks3)/3)
However, the ceil only rounds the number down but does not roll the number up.
There's 1 algorithm i stumbled upon
var roundedVal = Math.round(origVal*20)/20;
but i still can't figure a formula for some problem.

std::ceil
rounds up to the nearest integer
std::floor
rounds down to the nearest integer
std::round
performs the behavior you expect
please give a use case with numbers if this does not provide you with what you need!

You don't need a function to round in C or C++. You can just use a simple trick. Add 0.5 and then cast to an integer. That's probably all round does anyway.
double d = 3.1415;
double d2 = 4.7;
int i1 = (int)(d + 0.5);
int i2 = (int)(d2 + 0.5);
i1 is 3, and i2 is 5. You can verify it yourself.

The function you need is called round, believe it or not.
ceil rounds UP, btw. That is, to the closest larger integer. floor rounds down.

std::round may be the one you're looking for. However, bear in mind that it returns a float. You may want to try lround or llround to get a result in long or long long (C++ 11).
http://en.cppreference.com/w/cpp/numeric/math/round

In c++, by including cmath library we can use use various functions which rounds off the value both up or down.
std::trunc
This simply truncates the decimal part, thas is, the digits after the decimal point no matter what the decimal is.
std::ceil
This is used to round up to the closest integer value.
std::floor
This is used to round down to the closest integer value.
std::round
This will round to the nearest integer value whichever is the closest, that is, it can be round up or round down.

Related

Given an `int A` Is there a strong guarantee that `A == (int) (double) A`?

I need a strong guarantee that int x = (int) std::round(y) will always give the correct results (y is finite and "humanly", e.g. -50000 to 50000).
std::round(4.1) can give 4.000000000001 or 3.99999999999. In the latter case, casting to int gives 3, right?
To manage this, I reinvented the wheel with this ugly function:
template<std::integral S = int, std::floating_point T>
S roundi(T x)
{
S r = (S) x;
T r2 = std::fmod(x, 1);
if (r2 >= 0.5) return r + 1;
if (r2 <= -0.5) return r - 1;
return r;
}
But is this necessary? Or does casting from double to int use the last mantissa bit for rounding?
Assuming int is 32 bits wide and double is 64 bits wide (and assuming IEEE 754), all values of int are exactly representable in a double.
That means std::round(4.1) returns exactly 4. Nothing more nothing less. And casting that number to int is always 4 exactly.
std::round(4.1) can give 4.000000000001 or 3.99999999999. In later case, casting to int gives 3 right?
No, it cannot. The result of std::round is always an integer, exactly, with no rounding error.
I need strong guarantee that int x = (int) std::round(y) will give always the correct results (y is finite and "humanly" e.g. -50000 to
50000).
C++ inherits its floating-point model from C, and, per C 2018 5.2.4.2.2 12, double is capable of representing at least ten-digit integers, so [−50,000, +50,000] is well within its range. It is even within the range of float, which is capable of representing six-digit integers. This requirement extends back to C 1990.
Given an int A Is there a strong guarantee that A == (int) (double) A?
No, the C++ standard does not impose an upper limit on the width of int nor a relationship between with precision of int (number of bits it uses for the value, excluding the sign bit) and the precision of double (number of bits or other digits in its significand), so a C++ implementation may have an int with more precision than double.
std::round(4.1) can give 4.000000000001 or 3.99999999999. In later case, casting to int gives 3 right?
That's true. 4.1 can be seen as 4.0 (which has exact representation in floating point as an integer it is) plus 0.1, which can be seen as 1/10 (it's exactly 1/10, indeed) And the problem you will have is if you try to round a number close to that to one decimal point after the decimal mark (rounding to an integer multiple of 0.1 or 0.01 or 0.001, etc.)
If you are using decimal floating point (which normally C compilers don't) then you are lucky, as 0.1 is 10&^(-1) which again has an exact representation in the machine. But as a binary floating point number, it has an infinite representation in binary as 0.000110011001100110011001100...b and it depends where you cut the number you will get some value or another, but you will never get the exact value as a decimal number (with a finite number of digits)
But the way round() works is not that... if first adds 0.5 (which is exactly representable as a binary floating point number) to the number (this results in an exact operation, no rounding error emerges from it), and then cuts the integer part (which is also an exact operation), meaning that you are getting always an exact integer result (which is perfectly representable as an exact floating point, if the original number was). The rounding is equivalent to this set of operations:
(int)(4.1 + 0.5);
so you will get the integer part of 4.6 after addding the 0.5 part (or something like 4.60000000000000003, 4.59999999999999998, anyway both will be truncated to 4.0, which is also exactly representable in binary floating point format) so you will never get a wrong answer for the rounding to integer case... you can get a wrong response in case you get something close to 4.5 (which can round to 4.0 instead of the correct rounding to 5.0, but .5 happens to be exactly 0.1b in binary... and so it's not affected --
Beware although that rounding to multiples of a negative power of ten (0.1, 0.01, ...) is not warranted, as none of those numbers is representable exactly in binary floating point. All of them have an infinite representation as binary numbers, and due to the cutting at some point, they can be represented as a tiny number above or below (depending on which is close) and the rounding will not work.

How can I limit the amount of decimal places for a calculated float value?

When I calculated 5/2 the result is 2.500000, so I was wondering how I can limit the result of the float value to 2.50 instead. I am not using cout setprecision() or the fixed statement because I need the actual result of the arithmetic value to have only 2 decimal places.
If you do not want to use certain decimal places, how about using ceil(), floor(), round()?
First of all, 2/5 gives 2 because writing it like this will do integer division. Only 2.0f/5.0f will give you back a float.
Secondly, the only thing std::setprecision does is modify how many digits are displayed on the console when you do std::cout, it doesnt change the value of your variable or expression.
If you want to round your result to say one decimal place and not use standard functions, you could do something like
float a = 3.1415;
float b = ((int)(a*10+0.5))/10.0 // b is a rounded to one decimal place
but if you set std::setprecision to say 5 decimal places, it will still show you all the zeros after the last decimal place.

Rounding up and down a number C++

I'm trying to allow my program to round a number up and down respectively.
For example, if the number is 3.6, my program is suppose to round up the nearest number which is 4 and if the number is 3.4, it will be rounded down to 3.
I tried using the ceil library to get the average of 3 items.
results = ceil((marks1 + marks2 + marks3)/3)
However, the ceil only rounds the number down but does not roll the number up.
There's 1 algorithm i stumbled upon
var roundedVal = Math.round(origVal*20)/20;
but i still can't figure a formula for some problem.
std::ceil
rounds up to the nearest integer
std::floor
rounds down to the nearest integer
std::round
performs the behavior you expect
please give a use case with numbers if this does not provide you with what you need!
You don't need a function to round in C or C++. You can just use a simple trick. Add 0.5 and then cast to an integer. That's probably all round does anyway.
double d = 3.1415;
double d2 = 4.7;
int i1 = (int)(d + 0.5);
int i2 = (int)(d2 + 0.5);
i1 is 3, and i2 is 5. You can verify it yourself.
The function you need is called round, believe it or not.
ceil rounds UP, btw. That is, to the closest larger integer. floor rounds down.
std::round may be the one you're looking for. However, bear in mind that it returns a float. You may want to try lround or llround to get a result in long or long long (C++ 11).
http://en.cppreference.com/w/cpp/numeric/math/round
In c++, by including cmath library we can use use various functions which rounds off the value both up or down.
std::trunc
This simply truncates the decimal part, thas is, the digits after the decimal point no matter what the decimal is.
std::ceil
This is used to round up to the closest integer value.
std::floor
This is used to round down to the closest integer value.
std::round
This will round to the nearest integer value whichever is the closest, that is, it can be round up or round down.

C++ determining if a number is an integer

I have a program in C++ where I divide two numbers, and I need to know if the answer is an integer or not. What I am using is:
if(fmod(answer,1) == 0)
I also tried this:
if(floor(answer)==answer)
The problem is that answer usually is a 5 digit number, but with many decimals. For example, answer can be: 58696.000000000000000025658 and the program considers that an integer.
Is there any way I can make this work?
I am dividing double a/double b= double answer
(sometimes there are more than 30 decimals)
Thanks!
EDIT:
a and b are numbers in the thousands (about 100,000) which are then raised to powers of 2 and 3, added together and divided (according to a complicated formula). So I am plugging in various a and b values and looking at the answer. I will only keep the a and b values that make the answer an integer. An example of what I got for one of the answers was: 218624 which my program above considered to be an integer, but it really was: 218624.00000000000000000056982 So I need a code that can distinguish integers with more than 20-30 decimals.
You can use std::modf in cmath.h:
double integral;
if(std::modf(answer, &integral) == 0.0)
The integral part of answer is stored in fraction and the return value of std::modf is the fractional part of answer with the same sign as answer.
The usual solution is to check if the number is within a very short distance of an integer, like this:
bool isInteger(double a){
double b=round(a),epsilon=1e-9; //some small range of error
return (a<=b+epsilon && a>=b-epsilon);
}
This is needed because floating point numbers have limited precision, and numbers that indeed are integers may not be represented perfectly. For example, the following would fail if we do a direct comparison:
double d=sqrt(2); //square root of 2
double answer=2.0/(d*d); //2 divided by 2
Here, answer actually holds the value 0.99999..., so we cannot compare that to an integer, and we cannot check if the fractional part is close to 0.
In general, since the floating point representation of a number can be either a bit smaller or a bit bigger than the actual number, it is not good to check if the fractional part is close to 0. It may be a number like 0.99999999 or 0.000001 (or even their negatives), these are all possible results of a precision loss. That's also why I'm checking both sides (+epsilon and -epsilon). You should adjust that epsilon variable to fit your needs.
Also, keep in mind that the precision of a double is close to 15 digits. You may also use a long double, which may give you some extra digits of precision (or not, it is up to the compiler), but even that only gets you around 18 digits. If you need more precision than that, you will need to use an external library, like GMP.
Floating point numbers are stored in memory using a very different bit format than integers. Because of this, comparing them for equality is not likely to work effectively. Instead, you need to test if the difference is smaller than some epsilon:
const double EPSILON = 0.00000000000000000001; // adjust for whatever precision is useful for you
double remainder = std::fmod(numer, denom);
if(std::fabs(0.0 - remainder) < EPSILON)
{
//...
}
Alternatively, if you want to include values that are close to integers (based on your desired precision), you can modify the if condition slightly (since the remainder returned by std::fmod will be in the range [0, 1)):
if (std::fabs(std::round(d) - d) < EPSILON)
{
// ...
}
You can see the test for this here.
Floating point numbers are generally somewhat precise to about 12-15 digits (as a double), but as they are stored as a mantissa (fraction) and a exponent, rational numbers (integers or common fractions) are not likely to be stored as such. For example,
double d = 2.0; // d might actually be 1.99999999999999995
Because of this, you need to compare the difference of what you expect to some very small number that encompasses the precision you desire (we will call this value, epsilon):
double d = 2.0;
bool test = std::fabs(2 - d) < epsilon; // will return true
So when you are trying to compare the remainder from std::fmod, you need to check it against the difference from 0.0 (not for actual equality to 0.0), which is what is done above.
Also, the std::fabs call prevents you from having to do 2 checks by asserting that the value will always be positive.
If you desire a precision that is greater than 15-18 decimal places, you cannot use double or long double; you will need to use a high precision floating point library.

multiplication of double with integer precision

I have a double of 3.4. However, when I multiply it with 100, it gives 339 instead of 340. It seems to be caused by the precision of double. How could I get around this?
Thanks
First what is going on:
3.4 can't be represented exactly as binary fraction. So the implementation chooses closest binary fraction that is representable. I am not sure whether it always rounds towards zero or not, but in your case the represented number is indeed smaller.
The conversion to integer truncates, that is uses the closest integer with smaller absolute value.
Since both conversions are biased in the same direction, you can always get a rounding error.
Now you need to know what you want, but probably you want to use symmetrical rounding, i.e. find the closest integer be it smaller or larger. This can be implemented as
#include <cmath>
int round(double x) { std::floor(x + 0.5); } // floor is provided, round not
or
int round(double x) { return x < 0 ? x - 0.5 : x + 0.5; }
I am not completely sure it's indeed rounding towards zero, so please verify the later if you use it.
If you need full precision, you might want to use something like Boost.Rational.
You could use two integers and multiply the fractional part by multiplier / 10.
E.g
int d[2] = {3,4};
int n = (d[0] * 100) + (d[1] * 10);
If you really want all that precision either side of the decimal point. Really does depend on the application.
Floating-point values are seldom exact. Unfortunately, when casting a floating-point value to an integer in C, the value is rounded towards zero. This mean that if you have 339.999999, the result of the cast will be 339.
To overcome this, you could add (or subtract) "0.5" from the value. In this case 339.99999 + 0.5 => 340.499999 => 340 (when converted to an int).
Alternatively, you could use one of the many conversion functions provided by the standard library.
You don't have a double with the value of 3.4, since 3.4 isn't
representable as a double (at least on the common machines, and
most of the exotics as well). What you have is some value very
close to 3.4. After multiplication, you have some value very
close to 340. But certainly not 399.
Where are you seeing the 399? I'm guessing that you're simply
casting to int, using static_cast, because this operation
truncates toward zero. Other operations would likely do what
you want: outputting in fixed format with 0 positions after the
decimal, for example, rounds (in an implementation defined
manner, but all of the implementations I know use round to even
by default); the function round rounds to nearest, rounding
away from zero in halfway cases (but your results will not be
anywhere near a halfway case). This is the rounding used in
commercial applications.
The real question is what are you doing that requires an exact
integral value. Depending on the application, it may be more
appropriate to use int or long, scaling the actual values as
necessary (i.e. storing 100 times the actual value, or
whatever), or some sort of decimal arithmetic package, rather
than to use double.