Округление числа до 2 десятичных знаков в C - PullRequest
190 голосов
/ 28 августа 2009

Как можно округлить число с плавающей запятой (например, 37,777779) до двух десятичных знаков (37,78) в C?

Ответы [ 16 ]

4 голосов
/ 16 апреля 2014
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
3 голосов
/ 29 апреля 2016

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

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

Вот пример:

float x = ROUNDF(3.141592, 100)

х равен 3,14:)

2 голосов
/ 15 января 2019

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

#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
0 голосов
/ 03 апреля 2019

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

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 голосов
/ 12 мая 2017

Позвольте мне сначала попытаться обосновать причину добавления еще одного ответа на этот вопрос. В идеальном мире округление не имеет большого значения. Однако в реальных системах вам, возможно, придется столкнуться с несколькими проблемами, которые могут привести к округлению, которое может не соответствовать вашим ожиданиям. Например, вы можете выполнять финансовые расчеты, где окончательные результаты округляются и отображаются для пользователей в виде 2 десятичных знаков; эти же значения хранятся с фиксированной точностью в базе данных, которая может содержать более 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. В этом случае седьмое десятичное число, равное 9, заставляет функцию Round(val,6) давать ожидаемый результат. В этом случае может быть любое количество конечных 9 с.

Для 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 голосов
/ 24 февраля 2016

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

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, сдвигая точку влево и проверяя условие больше пяти

...