Ограничить точность с плавающей запятой?

Есть ли способ округлить плавающие точки до 2 точек? Например: 3576.7675745342556 становится 3576.76.


person jmasterx    schedule 01.08.2010    source источник
comment
Вы имеете в виду для отображения или расчета?   -  person    schedule 02.08.2010
comment
3576,7675745342556 становится 3576,77, не так ли?   -  person Vladimir    schedule 02.08.2010
comment
@Vladimir: Не то чтобы ненавязчиво. округление — это расплывчатый термин, который включает в себя несколько различных операций, имеющих более точное значение. Округление вверх/вниз/к нулю/к бесконечности/к ближайшему целому числу и т. д.   -  person Martin York    schedule 02.08.2010


Ответы (9)


round(x * 100) / 100.0

Если вы должны держать вещи плавающими:

roundf(x * 100) / 100.0

Гибкая версия с использованием функций стандартной библиотеки:

double GetFloatPrecision(double value, double precision)
{
    return (floor((value * pow(10, precision) + 0.5)) / pow(10, precision)); 
}
person strager    schedule 01.08.2010
comment
Обратите внимание, что, поскольку двоичная числа с плавающей запятой не может точно представлять большинство десятичных значений, этот ответ не будет работать, если вы начнете внимательно изучать младшие цифры. Но опять же, ни один другой ответ не может быть. - person Mark Ransom; 18.05.2013
comment
Почему вы используете floor вместо round в более гибкой версии? - person pooya13; 06.01.2021
comment
value * pow(10, precision) + 0.5 подход терпит неудачу 1) много отрицательных значений, 2) сложение вызывает неточность в промежуточных случаях, 3) переполнение умножения. - person chux - Reinstate Monica; 06.01.2021

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

In c++

cout << setprecision(2) << f; 

Для округления для отображения в графическом интерфейсе используйте std::ostringstream

person carlsborg    schedule 01.08.2010
comment
Никогда не ссылайтесь на другой ответ, как указано выше. Порядок отображения ответов меняется со временем и в соответствии с настраиваемыми пользователем предпочтениями (сортировка по времени или количеству голосов). Чтобы решить вашу конкретную проблему, вместо целочисленного приведения можно использовать floor или ceil. - person Ben Voigt; 02.08.2010
comment
@Svante, потому что мы используем C++? - person Craig; 02.08.2010
comment
Хотя cout может быть предпочтительнее в C++, вы можете использовать printf в C или C++. Например. std::printf(Printf C++\n); - person bn.; 02.08.2010
comment
Я имел в виду printf("%.2f", f);. - person Svante; 02.08.2010
comment
что # включает это? - person mLstudent33; 27.04.2020

Умножьте на 100, округлите до целого числа (как хотите), разделите на 100. Обратите внимание, что, поскольку 1/100 не может быть точно представлено в виде числа с плавающей запятой, рассмотрите возможность сохранения целых чисел с фиксированной точностью.

person Tassos Bassoukos    schedule 01.08.2010
comment
Десятичные целые числа с фиксированной точкой, вполне возможно, являются здесь действительно правильным ответом. - person caf; 02.08.2010

Для тех из вас, кто, как и я, гуглил, чтобы отформатировать поплавок в деньгах:

#include <iomanip>
#include <sstream>
#include <string>

std::string money_format (float val)
{
    std::ostringstream oss;

    oss << std::fixed << std::setfill ('0') << std::setprecision (2) << val;

    return oss.str();
}
// 12.3456 --> "12.35"
// 1.2 --> "1.20"

Вы должны вернуть его как строку. Вернув его обратно в поплавок, вы потеряете точность.

person xinthose    schedule 30.07.2015

Не используйте поплавки. Используйте целые числа, хранящие количество центов, и печатайте десятичную точку перед двумя последними знаками, если вы хотите напечатать доллары. Плавающие числа почти всегда неверны для денег, если только вы не выполняете упрощенные расчеты (например, наивные экономические математические модели), где действительно имеет значение только величина чисел, и вы никогда не вычитаете близлежащие числа.

person R.. GitHub STOP HELPING ICE    schedule 02.08.2010

попробуйте использовать

std::cout<<std::setprecision(2)<<std::cout<<x;

должно работать, и появляются только 2 цифры после плавающей запятой.

person Yassine Abdul-Rahman    schedule 24.07.2015

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

#include <sstream>

template<typename T>
T toPrecision(T input, unsigned precision)
{
    static std::stringstream ss;

    T output;
    ss << std::fixed;
    ss.precision(precision);
    ss << input;
    ss >> output;
    ss.clear();

    return output;
}

template<unsigned P, typename T>
T toPrecision(T input) { return toPrecision(input, P); }

// compile-time version
double newValue = toPrecision<2>(5.9832346739); // newValue: 5.98
// run-time version
double newValue = toPrecision(3.1415, 2); // newValue: 3.14

Вы также можете добавить статические проверки для T и precision (в случае подписи времени компиляции).

person pooya13    schedule 06.01.2021
comment
Дорогой подход, но функционально формирует лучший ответ даже в большинстве, если не во всех, крайних случаях. - person chux - Reinstate Monica; 06.01.2021
comment
@chux-ReinstateMonica Я сделал stringstream static, чтобы несколько снизить стоимость, и удалил сбивающий с толку комментарий. Ваше здоровье - person pooya13; 06.01.2021

Чтобы ограничить точность:
Если x — число с плавающей запятой, округление не выполняется:
(сдвиг вверх на 2 десятичных знака, удаление дроби, сдвиг вниз на 2 десятичных знака)

((int)(x*100.0)) / 100.0F

Плавающая с округлением:

((int)(x*100.0 + 0.5F)) / 100.0F

Двойной без округления:

((long int)(x*100.0)) / 100.0

Двойной с округлением:

((long int)(x*100.0 + 0.5)) / 100.0

Примечание. Поскольку x — это либо float, либо double, дробная часть всегда будет присутствовать. Это разница между тем, как представлен # (IEEE 754), и точностью #.
C99 поддерживает round()

person Doug    schedule 06.08.2013
comment
(int)(x*100.0) происходит сбой, когда продукт выходит за пределы диапазона int. Даже использование intmax_t недостаточно. x*100.0 + 0.5F терпит неудачу, как это. - person chux - Reinstate Monica; 06.01.2021

Попробуйте это, это работает отлично

float=3576.7675745342556;
printf("%.2f",float);

изменить некоторые объекты в нем, чтобы увидеть и изучить код.

person Adam Marsono Putra    schedule 15.10.2017