Число округлений до 2 десятичных мест в C

Как я могу объединить float (например, 37.777779) до двух знаков после запятой (37.78) в C?

+190
27 авг. '09 в 21:41
источник поделиться
17 ответов

Если вы просто хотите округлить число для целей вывода, то строка формата "%.2f" действительно является правильным ответом. Однако, если вы действительно хотите округлить значение с плавающей запятой для дальнейших вычислений, выполните следующие действия:

#include <math.h>

float val = 37.777779;

float rounded_down = floorf(val * 100) / 100;   /* Result: 37.77 */
float nearest = roundf(val * 100) / 100;  /* Result: 37.78 */
float rounded_up = ceilf(val * 100) / 100;      /* Result: 37.78 */

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

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

Для большей (много!) дополнительной информации о округлении, и особенно о правилах развязывания для округления до ближайшего, см. статью Википедии об округлении.

+378
27 авг. '09 в 23:21
источник

Связанные вопросы


Похожие вопросы

Использование %.2f в printf. Он печатает только 2 десятичных знака.

Пример:

printf("%.2f", 37.777779);

Выход:

37.77
+68
27 авг. '09 в 21:45
источник

Предполагая, что вы говорите о значении для печати, тогда Andrew Coleson и AraK ответят правильно:

printf("%.2f", 37.777779);

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

См. ссылку в Greg Hewgill ответьте на соответствующий вопрос, в котором также рассказывается, почему вы не должны использовать с плавающей точкой для финансовых расчетов.

+40
27 авг. '09 в 21:51
источник

Как насчет этого:

float value = 37.777779;
float rounded = ((int)(value * 100 + .5) / 100.0);
+23
27 авг. '09 в 23:21
источник
printf("%.2f", 37.777779);

Если вы хотите записать в C-строку:

char number[24]; // dummy size, you should take care of the size!
sprintf(number, "%.2f", 37.777779);
+19
27 авг. '09 в 21:45
источник

Не существует способа округлить float до другого float, потому что округленный float может быть не представимым (ограничение числа с плавающей запятой). Например, скажите, что вы округлены с 37.777779 по 37.78, но ближайший представимый номер равен 37.781.

Тем не менее, вы можете "закруглить" float с помощью строковой функции формата.

+11
27 авг. '09 в 21:47
источник

Кроме того, если вы используете С++, вы можете просто создать такую ​​функцию:

string prd(const double x, const int decDigits) {
    stringstream ss;
    ss << fixed;
    ss.precision(decDigits); // set # places after decimal
    ss << x;
    return ss.str();
}

Затем вы можете вывести любое двойное myDouble с n местами после десятичной точки с кодом, например:

std::cout << prd(myDouble,n);
+8
23 авг. '13 в 0:31
источник

Вы все еще можете использовать:

float ceilf(float x); // don't forget #include <math.h> and link with -lm.

Пример:

float valueToRound = 37.777779;
float roundedValue = ceilf(valueToRound * 100) / 100;
+7
27 авг. '09 в 23:04
источник

В С++ (или в C с приложением C-стиля) вы можете создать функцию:

/* Function to control # of decimal places to be output for x */
double showDecimals(const double& x, const int& numDecimals) {
    int y=x;
    double z=x-y;
    double m=pow(10,numDecimals);
    double q=z*m;
    double r=round(q);

    return static_cast<double>(y)+(1.0/m)*r;
}

Тогда std::cout << showDecimals(37.777779,2); произведет: 37.78.

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

+6
21 авг. '12 в 21:11
источник

Используйте float roundf(float x).

"Круглые функции округляют свой аргумент до ближайшего целочисленного значения в формате с плавающей запятой, округляя половину случаев от нуля, независимо от текущего направления округления." C11dr §7.12.9.5

#include <math.h>
float y = roundf(x * 100.0f) / 100.0f; 

В зависимости от вашей реализации float числа, которые могут показаться на полпути, не являются. поскольку плавающая точка обычно ориентирована на базу 2. Более того, точное округление до ближайшего 0.01 во всех случаях "на полпути" является наиболее сложным.

void r100(const char *s) {
  float x, y;
  sscanf(s, "%f", &x);
  y = round(x*100.0)/100.0;
  printf("%6s %.12e %.12e\n", s, x, y);
}

int main(void) {
  r100("1.115");
  r100("1.125");
  r100("1.135");
  return 0;
}

 1.115 1.115000009537e+00 1.120000004768e+00  
 1.125 1.125000000000e+00 1.129999995232e+00
 1.135 1.134999990463e+00 1.139999985695e+00

Хотя "1.115" "на полпути" между 1.11 и 1.12, при преобразовании в float значение 1.115000009537... и больше не "на полпути" , но ближе к 1.12 и раундам ближе к ближайшему float of 1.120000004768...

"1.125" - "на полпути" между 1.12 и 1.13, при преобразовании в float значение равно 1.125 и является "на полпути" . Он округляется к 1.13 из-за связей с четным правилом и раундами до ближайшего float от 1.129999995232...

Хотя "1.135" "на полпути" между 1.13 и 1.14, при преобразовании в float значение 1.134999990463... и больше не "на полпути" , а ближе к 1.13 и раундам ближе к ближайшему float of 1.129999995232...

Если используется код

y = roundf(x*100.0f)/100.0f;

Хотя "1.135" - "на полпути" между 1.13 и 1.14, при преобразовании в float значение 1.134999990463... и больше не "на полпути" , а ближе к 1.13, а неправильно до float из 1.139999985695... из-за более ограниченной точности float vs. double. Это неправильное значение может считаться правильным, в зависимости от целей кодирования.

+4
03 авг. '14 в 17:50
источник
double f_round(double dval, int n)
{
    char l_fmtp[32], l_buf[64];
    char *p_str;
    sprintf (l_fmtp, "%%.%df", n);
    if (dval>=0)
            sprintf (l_buf, l_fmtp, dval);
    else
            sprintf (l_buf, l_fmtp, dval);
    return ((double)strtod(l_buf, &p_str));

}

Здесь n - число десятичных знаков

Пример:

double d = 100.23456;

printf("%f", f_round(d, 4));// result: 100.2346

printf("%f", f_round(d, 2));// result: 100.23
+4
16 апр. '14 в 2:53
источник

Я сделал этот макрос для округления чисел с плавающей точкой. Добавьте это в свой заголовок/существо файла

#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))

Вот пример:

float x = ROUNDF(3.141592, 100)

х равен 3,14 :)

+3
29 апр. '16 в 15:06
источник

Определение кода:

#define roundz(x,d) ((floor(((x)*pow(10,d))+.5))/pow(10,d))

Результаты:

a = 8.000000
sqrt(a) = r = 2.828427
roundz(r,2) = 2.830000
roundz(r,3) = 2.828000
roundz(r,5) = 2.828430
+2
15 янв. '19 в 10:29
источник

Попробуйте это. он даст двойной с двумя знаками после запятой.

                int ttt = round(value * 100);
                string str = to_string(ttt);
                str.insert (str.end()-2,1,'.');
                double temp = ::strtod(str.c_str(), 0);
                obPrinciple = temp;
0
21 сент. '16 в 12:51
источник

Позвольте мне сначала попытаться оправдать мою причину добавления еще одного ответа на этот вопрос. В идеальном мире округление на самом деле не имеет большого значения. Однако в реальных системах вам может потребоваться несколько проблем, которые могут привести к округлению, что может и не быть тем, что вы ожидаете. Например, вы можете выполнять финансовые расчеты, когда конечные результаты округляются и отображаются пользователям как 2 десятичных знака; эти же значения хранятся с фиксированной точностью в базе данных, которая может содержать более двух знаков после запятой (по разным причинам, нет оптимального количества мест для хранения... зависит от конкретных ситуаций, которые должна поддерживать каждая система, например, крошечных предметов, чьи цены представляют собой доли копейки за единицу); и вычисления с плавающей запятой выполняются с значениями, где результаты равны плюс/минус эпсилон. Я столкнулся с этими проблемами и развивал свою собственную стратегию на протяжении многих лет. Я не буду утверждать, что я столкнулся со всеми сценариями или получил лучший ответ, но ниже приведен пример моего подхода, который преодолевает эти проблемы:

Предположим, что 6 десятичных знаков считаются достаточной точностью для вычислений по поплавкам/удвоениям (произвольное решение для конкретного приложения) с использованием следующей функции/метода округления:

double Round(double x, int p)
{
    if (x != 0.0) {
        return ((floor((fabs(x)*pow(double(10.0),p))+0.5))/pow(double(10.0),p))*(x/fabs(x));
    } else {
        return 0.0;
    }
}

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

double val;
// ...perform calculations on val
String(Round(Round(Round(val,8),6),2));

Для val = 6.825 результат 6.83, как ожидалось.

Для val = 6.824999 результат 6.82. Здесь предположение состоит в том, что расчет привел в точности к 6.824999, а седьмое десятичное число - нулю.

Для val = 6.8249999 результат 6.83. 7-е число после запятой 9 в этом случае заставляет функцию Round(val,6) дать ожидаемый результат. Для этого случая может быть любое количество конечных 9 s.

Для val = 6.824999499999 результат 6.83. Округление до восьмого десятичного знака в качестве первого шага, т.е. Round(val,8), заботится о одном неприятном случае, когда вычисляемый результат с плавающей запятой вычисляется до 6.8249995, но внутренне представлен как 6.824999499999....

Наконец, пример из вопроса... val = 37.777779 приводит к 37.78.

Этот подход может быть далее обобщен как:

double val;
// ...perform calculations on val
String(Round(Round(Round(val,N+2),N),2));

где N - точность, которая должна поддерживаться для всех промежуточных вычислений по поплавкам/удвоениям. Это работает и с отрицательными значениями. Я не знаю, является ли этот подход математически правильным для всех возможностей.

0
12 мая '17 в 19:13
источник

... или вы можете сделать это старомодным способом без каких-либо библиотек:

float a = 37.777779;

int b = a; // b = 37    
float c = a - b; // c = 0.777779   
c *= 100; // c = 77.777863   
int d = c; // d = 77;    
a = b + d / (float)100; // a = 37.770000;

Это, конечно, если вы хотите удалить дополнительную информацию из номера.

0
03 апр. '19 в 13:31
источник

эта функция принимает число и точность и возвращает округленное число

float roundoff(float num,int precision)
{
      int temp=(int )(num*pow(10,precision));
      int num1=num*pow(10,precision+1);
      temp*=10;
      temp+=5;
      if(num1>=temp)
              num1+=10;
      num1/=10;
      num1*=10;
      num=num1/pow(10,precision+1);
      return num;
}

он преобразует число с плавающей запятой в int по левому сдвигу точки и проверяет более пяти условий.

-1
24 февр. '16 в 17:37
источник

Посмотрите другие вопросы по меткам или Задайте вопрос