Redondeo del número a 2 lugares decimales en C

¿Cómo puedo redondear un flotante (como 37.777779) a dos decimales (37.78) en C?

Si solo desea redondear el número para fines de salida, entonces la cadena de formato "%.2f" es la respuesta correcta. Sin embargo, si realmente desea redondear el valor del punto flotante para realizar más cálculos, algo como lo siguiente funciona:

 #include  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 */ 

Observe que hay tres reglas de redondeo diferentes que puede elegir: redondear hacia abajo (es decir, truncar después de dos lugares decimales), redondear al más cercano y redondear hacia arriba. Por lo general, quieres redondear al más cercano.

Como han señalado varios otros, debido a las peculiaridades de la representación en coma flotante, estos valores redondeados pueden no ser exactamente los valores decimales “obvios”, pero estarán muy cerca.

Para obtener más (¡mucho!) Más información sobre el redondeo, y especialmente sobre las reglas de desempate para redondear al más cercano, vea el artículo de Wikipedia sobre Redondeo .

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

Suponiendo que está hablando de redondear el valor de impresión, entonces Andrew Coleson y la respuesta de AraK son correctas:

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

Pero tenga en cuenta que si pretende redondear el número a exactamente 37.78 para uso interno (por ejemplo, comparar con otro valor), entonces esta no es una buena idea, debido a la forma en que funcionan los números flotantes: generalmente no lo hace desea hacer comparaciones de igualdad para el punto flotante, en su lugar use un valor objective +/- un valor sigma. O codifica el número como una cadena con una precisión conocida, y compara eso.

Vea el enlace en la respuesta de Greg Hewgill a una pregunta relacionada , que también explica por qué no debe usar el punto flotante para los cálculos financieros.

Qué tal esto:

 float value = 37.777779; float rounded = ((int)(value * 100 + .5) / 100.0); 
 printf("%.2f", 37.777779); 

Si quieres escribir en C-string:

 char number[24]; // dummy size, you should take care of the size! sprintf(number, "%.2f", 37.777779); 

No hay forma de redondear un float a otro float porque el float redondeado puede no ser representable (una limitación de los números de coma flotante). Por ejemplo, digamos que redondea 37.777779 a 37.78, pero el número representable más cercano es 37.781.

Sin embargo, puede “redondear” un float utilizando una función de cadena de formato.

Además, si está usando C ++, puede crear una función como esta:

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

A continuación, puede generar cualquier doble myDouble con n lugares después del punto decimal con un código como este:

 std::cout << prd(myDouble,n); 

Aún puedes usar:

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

ejemplo:

 float valueToRound = 37.777779; float roundedValue = ceilf(valueToRound * 100) / 100; 

En C ++ (o en C con moldes de estilo C), puede crear la función:

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

Luego std::cout << showDecimals(37.777779,2); produciría: 37.78.

Obviamente no necesitas crear las 5 variables en esa función, pero las dejo allí para que puedas ver la lógica. Probablemente haya soluciones más simples, pero esto funciona bien para mí, especialmente porque me permite ajustar el número de dígitos después del lugar decimal que necesito.

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

Aquí n es el número de decimales

ejemplo:

 double d = 100.23456; printf("%f", f_round(d, 4));// result: 100.2346 printf("%f", f_round(d, 2));// result: 100.23 

Use float roundf(float x) .

“La ronda funciona alrededor de su argumento con el valor entero más cercano en formato de punto flotante, redondeando casos a medio camino de cero, independientemente de la dirección actual de redondeo”. C11dr §7.12.9.5

 #include  float y = roundf(x * 100.0f) / 100.0f; 

Dependiendo de la implementación de su float , los números que pueden parecer a mitad de camino no lo son. como punto flotante es típicamente orientado a base 2. Además, redondear con precisión al 0.01 más cercano en todos los casos “a mitad de camino” es más desafiante.

 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 

Aunque “1.115” está “a mitad de camino” entre 1.11 y 1.12, cuando se convierte a float , el valor es 1.115000009537... y ya no está “a mitad de camino”, sino más cerca de 1.12 y redondea al float más cercano de 1.120000004768...

“1.125” es “a mitad de camino” entre 1.12 y 1.13, cuando se convierte a float , el valor es exactamente 1.125 y es “a mitad de camino”. Se redondea hacia 1.13 debido a los vínculos con reglas pares y redondea al float más cercano de 1.129999995232...

Aunque “1.135” está “a mitad de camino” entre 1.13 y 1.14, cuando se convierte a float , el valor es 1.134999990463... y ya no está “a medio camino”, sino más cerca de 1.13 y redondea al float más cercano de 1.129999995232...

Si el código utilizado

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

Aunque “1.135” es “a mitad de camino” entre 1.13 y 1.14, cuando se convierte a float , el valor es 1.134999990463... y ya no está “a mitad de camino”, sino más cerca de 1.13 pero redondea incorrectamente a float de 1.139999985695... debido a la precisión más limitada de float vs. double . Este valor incorrecto puede verse como correcto, dependiendo de los objectives de encoding.

Hice esta macro para redondear números flotantes. Añádalo a su encabezado / archivo

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

Aquí hay un ejemplo:

 float x = ROUNDF(3.141592, 100) 

x es igual a 3.14 🙂

Permítanme primero intentar justificar mi razón para agregar otra respuesta a esta pregunta. En un mundo ideal, el redondeo no es realmente un gran problema. Sin embargo, en sistemas reales, es posible que tenga que lidiar con varios problemas que pueden provocar un redondeo que puede no ser el esperado. Por ejemplo, puede realizar cálculos financieros en los que los resultados finales se redondean y se muestran a los usuarios con dos decimales; estos mismos valores se almacenan con precisión fija en una base de datos que puede incluir más de dos decimales (por diversas razones, no hay un número óptimo de lugares para guardar … depende de situaciones específicas que cada sistema debe admitir, por ejemplo, artículos pequeños cuyos precios son fracciones de un centavo por unidad); y, cálculos en coma flotante realizados en valores donde los resultados son más / menos epsilon. He estado enfrentando estos problemas y desarrollando mi propia estrategia a lo largo de los años. No afirmaré que he enfrentado cada escenario o que tengo la mejor respuesta, pero a continuación se muestra un ejemplo de mi enfoque que supera estos problemas:

Supongamos que 6 decimales se consideran como precisión suficiente para los cálculos en flotantes / dobles (una decisión arbitraria para la aplicación específica), usando la siguiente función / método de redondeo:

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

El redondeo a 2 decimales para la presentación de un resultado se puede realizar como:

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

Para val = 6.825 , el resultado es 6.83 como se esperaba.

Para val = 6.824999 , el resultado es 6.82 . Aquí la suposición es que el cálculo dio como resultado exactamente 6.824999 y el séptimo lugar decimal es cero.

Para val = 6.8249999 , el resultado es 6.83 . El séptimo lugar decimal es 9 en este caso hace que la función Round(val,6) dé el resultado esperado. Para este caso, podría haber cualquier cantidad de 9 s seguidos.

Para val = 6.824999499999 , el resultado es 6.83 . Redondeando al octavo lugar decimal como primer paso, es decir, Round(val,8) , se ocupa del desagradable caso en el que un resultado flotante calculado calcula a 6.8249995 , pero se representa internamente como 6.824999499999...

Finalmente, el ejemplo de la pregunta … val = 37.777779 da val = 37.777779 resultado 37.78 .

Este enfoque podría generalizarse aún más como:

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

donde N es la precisión que debe mantenerse para todos los cálculos intermedios en flotantes / dobles. Esto también funciona con valores negativos. No sé si este enfoque es matemáticamente correcto para todas las posibilidades.

esta función toma el número y la precisión y devuelve el número redondeado

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

convierte el número de coma flotante en int al desplazar el punto hacia la izquierda y verificar si hay más de cinco.

Prueba este. Le dará un double con dos decimales:

 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;