31

I am having trouble rounding a GPA double to 2 decimal places. (ex of a GPA needed to be rounded: 3.67924) I am currently using ceil to round up, but it currently outputs it as a whole number (368)

here is what I have right now

if (cin >> gpa) {
    if (gpa >= 0 && gpa <= 5) {
           // valid number

           gpa = ceil(gpa * 100);

           break;
    } else {
           cout << "Please enter a valid GPA (0.00 - 5.00)" << endl;
           cout << "GPA: ";

    }
}

using the above code with 3.67924 would output 368 (which is what I want, but just without the period between the whole number and the decimals). How can I fix this?

Bryce Hahn
  • 1,585
  • 4
  • 16
  • 26
  • 3
    After you multiplied by 100 and rounded, divide back by 100. Or, if all you need is to **print** with two decimal places, keep the value unchanged and use [`setprecision`](http://en.cppreference.com/w/cpp/io/manip/setprecision) when printing. – Igor Tandetnik Sep 19 '14 at 02:12
  • The title mentions rounding up, but the problem statement mentions rounding. Rounding could be implemented with gpa = floor((100.*gpa)+.5)/100. – rcgldr Sep 19 '14 at 03:09
  • 1
    `would output 368 (which is what I want, but just without the period between the whole number and the decimals). How can I fix this?` you would do this `gpa /= 100` assuming `gpa` is a `double`. – Fantastic Mr Fox Sep 19 '14 at 03:30
  • Read http://floating-point-gui.de/ – Basile Starynkevitch Sep 19 '14 at 04:22

7 Answers7

47

To round a double up to 2 decimal places, you can use:

#include <iostream>
#include <cmath>

int main() {
    double value = 0.123;
    value = std::ceil(value * 100.0) / 100.0;
    std::cout << value << std::endl; // prints 0.13
    return 0;
}

To round up to n decimal places, you can use:

double round_up(double value, int decimal_places) {
    const double multiplier = std::pow(10.0, decimal_places);
    return std::ceil(value * multiplier) / multiplier;
}

This method won't be particularly fast, if performance becomes an issue you may need another solution.

kaveish
  • 1,296
  • 12
  • 21
  • 8
    In my specific case I preferred to use `std::round` instead of `std::ceil`, but your solution was absolutely perfect. Thanks! – Brutus Mar 31 '20 at 12:51
16

If it is just a matter of writing to screen then to round the number use

std::cout.precision(3);
std::cout << gpa << std::endl;

see

floating points are not exactly represented so by internally rounding the value and then using that in your calculations you are increasing the inexactness.

AndersK
  • 35,813
  • 6
  • 60
  • 86
6

When you are trying to store values upto n decimal values in a variable . You have to multiple that value with 10^n and divide the same with 10^n. Afterward use type operator to manipulate in the program. Here is the example : -

 float a,b,c,d,sum;

 cin>>a>>b>>c>>d; // reading decimal values

sum=(a*b*c*d);

sum=round(sum*100)/100; // here it is for 2 decimal points

if((float)sum < (float) 9.58)
  cout<<"YES\n";
else
  cout<<"NO\n";  
prashant bade
  • 71
  • 1
  • 2
5

You can't round doubles to two decimal places. Doubles don't have decimal places. They have binary places, and they aren't commensurable with decimal places.

If you want decimal places, you must use a decimal radix, e.g. when formatting for output with printf("%.2f", ...).

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 10
    True, but not necessarily helpful - it's still common enough to want the *nearest* `double` to the intended 2-decimal-digit number, for example - as a step before doing some other calculation to minimise further errors. – Tony Delroy Sep 19 '14 at 03:33
  • 1
    @TonyD He says he wants `3.68`. Nothing about the 'nearest'. – user207421 Sep 19 '14 at 03:47
  • 1
    @TonyDelroy And premature rounding will *cause* further errors. – user207421 Jun 26 '20 at 08:13
  • When you narrow the scenarios to those characterised as "premature", sure - the word implies an error. But other times _earlier_ rounding is the best way to use doubles to calculate something and shouldn't be termed "premature". E.g. if a contract said a discount applied on a per-item basis, rounded up, then that should be done before multiplication by the quantity of items involved. There *can* be value in having the closest possible double representation to a specific two-decimal-place-value, even when you know it's not that exact thing. Incidentally, it may be exact - e.g. 0.25, 0.75. – Tony Delroy Jun 26 '20 at 19:59
  • 1
    @TonyDelroy There can be what value? The time to do the rounding is at the end when you arrive at the decimal radix. – user207421 Oct 24 '20 at 09:10
  • I already gave you an example of when it may have value above - rounding item prices before multiplying by quantity, if the business logic is that it should work that way. For example, it might be item price * 0.9 (for 10% discount), rounded, then multiplied by qty, then round that again. You could of course do the pricing using integers for greater assurances, but if you're using doubles (as many systems do), then it may well be that rounding at all the right times prevents errors at any given stage compounding to change the overall result. – Tony Delroy Oct 25 '20 at 04:40
  • 1
    This answer is the right one actually. The result is simply wrong in some cases if you use binary floating point number, like round(0.575, 2) won't be correct using any of the other answers. You just have to use decimal numbers to get the right answer. – Yuhta Aug 03 '23 at 23:13
  • @TonyDelroy The fewer times you round, the smaller will be the rounding errors. There are no two ways about this. – user207421 Aug 04 '23 at 03:51
2

Try this. But your cout statement in else condition, so it won't give the desired output for 3.67924.

if (cin >> gpa)
{     
    if (gpa >= 0 && gpa <= 5) {
        // valid number

        gpa = ceil(gpa * 100);
        gpa=gpa/100;
        break;
    } 
    else
    {    
       cout << "Please enter a valid GPA (0.00 - 5.00)" << endl;    
       cout << "GPA: ";
    }
}
MD. Khairul Basar
  • 4,976
  • 14
  • 41
  • 59
2

Example: you want 56.899999999999 to be output as a string with 2 decimal point which is 56.89.

First, convert them
value = 56.89 * 1000 = 5689
factor = 100
- 1 decimal point = 10
- 2 decimal point = 100
- 3 decimal point = 1000
etc

int integerValue;
int decimal;
std::string result;
function ( int value , int factor)
{
    integerValue= (value / factor) * factor; //(5689 / 100) * 100 = 5600
    decimal = value - integerValue;  // 5689 - 5600;
    result = std::to_string((int)(value/factor) + "." + std::to_string(decimal); 
    // result = "56" + "." + "89" 
    // lastly, print result
}

Not sure if this can help?

Goh Allant
  • 29
  • 2
-1
std::string precision_2(float number)
{
    int decimal_part = (number * 100) - ((int)number * 100);
    if (decimal_part > 10) {
        return std::to_string((int)number) + "." + std::to_string(decimal_part);
    } else {
        return std::to_string((int)number) + ".0" + std::to_string(decimal_part);
    }
}

Handles well for all positive floats. A minor modification will make it work for -ves as well.

  • This is an old thread which has been answered before by many people. Thanks for contributing to the community, but maybe focus your effort on recently opened unanswered questions. – jpnadas Jun 23 '20 at 11:41