С++ округлить двойное число до 2 знаков после запятой

У меня возникли проблемы с округлением двойного среднего балла до 2 знаков после запятой. (например, средний балл нужно округлить: 3,67924) В настоящее время я использую ceil для округления, но в настоящее время он выводит его как целое число (368)

вот что у меня есть прямо сейчас

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: ";

    }
}

использование приведенного выше кода с 3,67924 приведет к выводу 368 (это то, что я хочу, но только без точки между целым числом и десятичными знаками). Как я могу это исправить?


person Bryce Hahn    schedule 19.09.2014    source источник
comment
После умножения на 100 и округления разделите обратно на 100. Или, если все, что вам нужно, это печатать с двумя знаками после запятой, оставьте значение без изменений и используйте setprecision при печати.   -  person Igor Tandetnik    schedule 19.09.2014
comment
В заголовке упоминается округление, но в постановке задачи упоминается округление. Округление может быть реализовано с помощью gpa = floor((100.*gpa)+.5)/100.   -  person rcgldr    schedule 19.09.2014
comment
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? вы бы сделали это gpa /= 100 при условии, что gpa является double.   -  person Fantastic Mr Fox    schedule 19.09.2014
comment
Читать floating-point-gui.de   -  person Basile Starynkevitch    schedule 19.09.2014


Ответы (7)


Чтобы округлить двойное значение до 2 знаков после запятой, вы можете использовать:

#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;
}

Чтобы округлить до n знаков после запятой, вы можете использовать:

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

Этот метод не будет особенно быстрым, если производительность станет проблемой, вам может понадобиться другое решение.

person kaveish    schedule 12.08.2019
comment
В моем конкретном случае я предпочел использовать std::round вместо std::ceil, но ваше решение было абсолютно идеальным. Спасибо! - person Brutus; 31.03.2020

Если это просто вопрос записи на экран, то для округления числа используйте

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

см.

числа с плавающей запятой точно не представлены, поэтому, округляя значение внутри, а затем используя его в своих расчетах, вы увеличиваете неточность.

person AndersK    schedule 15.03.2017

Вы не можете округлить двойное число до двух знаков после запятой. Двойники не имеют десятичные разряды. У них двоичные разряды, и они несоизмеримы с десятичными разрядами.

Если вам нужны десятичные разряды, вы должны использовать десятичную систему счисления, например. при форматировании для вывода с помощью printf("%.2f", ...).

person user207421    schedule 19.09.2014
comment
Верно, но не обязательно полезно — все еще достаточно часто требуется, чтобы ближайшее double соответствовало предполагаемому 2-значному числу, например — в качестве шага перед выполнением каких-либо других вычислений, чтобы свести к минимуму дальнейшие ошибки. - person Tony Delroy; 19.09.2014
comment
@TonyD Он говорит, что хочет 3.68. Ничего о «ближайшем». - person user207421; 19.09.2014
comment
@TonyDelroy И преждевременное округление вызовет дополнительные ошибки. - person user207421; 26.06.2020
comment
Когда вы сужаете сценарии до тех, которые характеризуются как преждевременные, конечно, это слово подразумевает ошибку. Но в других случаях ранее округление — это лучший способ использовать двойные числа для вычисления чего-либо, и его не следует называть преждевременным. Например. если в контракте указано, что скидка применяется на единицу товара с округлением в большую сторону, то это следует сделать до умножения на количество задействованных товаров. Может быть полезным иметь максимально близкое двойное представление к конкретному значению с двумя десятичными разрядами, даже если вы знаете, что это не совсем то. Между прочим, это может быть точно - например. 0,25, 0,75. - person Tony Delroy; 26.06.2020
comment
@TonyDeldroy Какое может быть значение? Время для округления наступает в конце, когда вы достигаете десятичной системы счисления. - person user207421; 24.10.2020
comment
Я уже привел вам пример, когда это может иметь значение выше - округление цен на товары перед умножением на количество, если бизнес-логика такова, что это должно работать именно так. Например, это может быть цена товара * 0,9 (для скидки 10%), округленная, затем умноженная на количество, а затем снова округленная. Вы, конечно, можете рассчитать цену, используя целые числа для большей уверенности, но если вы используете двойные числа (как это делают многие системы), то вполне может случиться так, что округление в нужное время предотвратит ошибки на любом данном этапе, в результате чего изменится общая сумма. результат. - person Tony Delroy; 25.10.2020

Попробуй это. Но ваш оператор cout в другом состоянии, поэтому он не даст желаемого результата для 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: ";
    }
}
person MD. Khairul Basar    schedule 19.09.2014

Пример: вы хотите, чтобы 56,899999999999 выводилось в виде строки с 2 десятичными точками, что равно 56,89.

Сначала преобразуйте их
значение = 56,89 * 1000 = 5689
фактор = 100
- 1 десятичный знак = 10
- 2 десятичных знака = 100
- 3 десятичная точка = 1000
и т. д.

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
}

Не уверены, что это может помочь?

person Goh Allant    schedule 25.10.2019

Когда вы пытаетесь сохранить значения до n десятичных значений в переменной. Вы должны умножить это значение на 10^n и разделить его на 10^n. После этого используйте оператор типа для манипулирования в программе. Вот пример: -

 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";  
person prashant bade    schedule 03.04.2021

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);
    }
}

Хорошо справляется со всеми положительными поплавками. Небольшая модификация заставит его работать и для -ves.

person Aravindhan Krishnan    schedule 23.06.2020
comment
Это старая тема, на которую уже ответили многие люди. Спасибо за вклад в сообщество, но, возможно, сосредоточьте свои усилия на недавно открытых вопросах, оставшихся без ответа. - person jpnadas; 23.06.2020