Problems with rounding a float number - c

I have the following source code but the result is not rounding to 2 decimal places.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main(int argc, char *argv[])
{
float x1=0;
float x2 = 0;
float result=0;
x1 = 8961.650391;
result = x1 * 100 + 0.5;
result = (float)floor(result);
printf("Result = <%f>\n", result);
result = result/100;
x2 = result;
printf("x2 = <%f>\n", x2);
return 0;
}
Please help to resolve the problem.
Result = <896165.000000>
x2 = <8961.650391>
How can obtain x3 = 8961.650000?

use "%0.2f" instead of %f , it will print value upto 2 decimal
x2= roundf(result * 100) / 100;
printf("x2 = <%0.2f>\n", x2);

float can typically represent about 232 different numbers exactly.
After all, it is typically encoded using 32-bits.
8961.65 is not one of them. The closest float to 8961.65 is 8961.650390625f. The below shows the previous and subsequent float.
To print a float to the nearest 0.01, use "%.2f" as suggest well by #pritesh agrawal.
Recommend rounding with rint() or round().
int main(void) {
float x = 8961.650391f;
float x100 = rint(x * 100.0);
float result = x100 / 100.0f;
printf("%f %.2f\n", nextafterf(x, 0), nextafterf(x, 0));
printf("%f %.2f\n", x, x);
printf("%f %.2f\n", nextafterf(x, x * 2), nextafterf(x, x * 2));
printf("%f %.2f\n", x100, x100);
printf("%f %.2f\n", result, result);
return 0;
}
Output
8961.649414 8961.65
8961.650391 8961.65
8961.651367 8961.65
896165.000000 896165.00
8961.650391 8961.65
How can obtain x3 = 8961.650000?
x3 cannot have the exact value of 8961.650000. To print a value, rounded to 2 decimal places followed by 4 zeros, the below can be used, but it is a bit of chicanery.
printf("%.2f0000\n", 8961.650390625f);
// output 8961.650000

Related

Specifying float or double yet getting int value

#include <stdio.h>
int diameter_fn(int r)
{
return (2 * r);
}
void circumference_fn(int r)
{
float pie = 22 / 7;
float circum = (2 * pie * r);
printf(", Circumference = %f", circum);
}
void area_fn(int r)
{
float pie = 22 / 7;
float area = (22 * r * r / 7);
printf(" & the Area = %f", area);
}
int main()
{
printf("\nName = Parth_Agrawal & UID = 22BCS10924\n");
int radius;
printf("Enter the Radius of Circle:\t\t");
scanf("%d", &radius);
printf("\nDiameter = %d", diameter_fn(radius));
circumference_fn(radius);
area_fn(radius);
return 0;
}
I want to calculate Circumference, diameter and area of circle using functions yet I get non-perfect Circumference and area values.
I already tried replacing the float with double, %f with %lf etc but I am always getting the Circumference and area in xxx.0000 format,I.e, similar to Int converted to float format.
Like the area for 4 unit radius is 50.27 but it is giving me 50.000000 which is too much annoying.
This is the Result I am getting
whereas this is the Result which I should get
... but it is giving me 50.000000 ...
OP is using integer math in many places where floating point math is needed.
void circumference_fn(int r) {
float pie = 22 / 7; // Integer math!!
float circum = (2 * pie * r);
printf(", Circumference = %f", circum);
}
void area_fn(int r) {
float pie = 22 / 7; // Integer math!! pie not used
float area = (22 * r * r / 7);// Integer math!!
printf(" & the Area = %f", area);
}
Instead use FP math.
Scant reason to use float. Use double as the default FP type.
Rather than approximate π with 22/7, use a more precise value.
#define PIE 3.1415926535897932384626433832795
void circumference_fn(int r) {
double circum = (2 * PIE * r);
printf(", Circumference = %f", circum);
}
void area_fn(int r) {
double area = PIE * r * r;
printf(" & the Area = %f", area);
}
Other
All three functions should take a double argument and return a double.
Use "%g" for printing. It is more informative with wee values and less verbose with large ones.
#Shawn is right: you are using integer math to calculate Pi. You should #include <math.h> and use M_PI instead of trying to calculate it yourself.

How to round DOWN to 2 decimal in C

So I am trying to round DOWN to 2 decimal places in C - EDIT: I actually need to change the value, not just display it to 2 decimals.
For example:
double x = 0.1234;
x = 0.12;
double y = 3.14159;
y = 3.14;
Is the an integrated function in <math.h> similar to floor(), or is there another way to do this?
Well I need to value to change so I used x = (double)((int)(x*100))/100;
This works, but you are limited to a relatively low range, i.e: 123456789 * 100 overflows.
Check if modf helps:
#include <stdio.h>
#include <math.h>
double dec2(double number)
{
double fractpart, intpart;
fractpart = modf(number, &intpart);
return intpart + round(fractpart * 100) * 0.01;
}
int main(void)
{
printf("%f\n", dec2(0.1234));
printf("%f\n", dec2(3.14159));
return 0;
}
Output:
0.120000
3.140000
If you want to display a float or double with 2 decimal places, specify a precision of 2 when using the %f format specifier.
printf("x=%.2f", x);

Calculating Maxwell-Boltzmann Distribution

I am trying to calculate Maxwell-Boltzmann Distribution but this code gives 0.00000, what is the problem?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
float e=2.718228183, pi=3.14159265, m=2.66*pow(10,-23), t, k=1.38*pow(10,-23), v, result;
scanf("%f %f", &t, &v);
result = sqrt(pow( m / (2*pi*k*t), 3)) * 4 * pi * pow(v,2) * pow(e, -(m * pow(v,2)) / (2*k*t));
printf("%f", result);
}
As described in the comments, the use of float together with the reduced precision of the constants give a result that is not representable anymore as a float. Changing the data type to double alone gives two decimal digits of accuracy. If we use exp, more digits for pi and do a bit of recombination of the computations we get 12 digits of accuracy. E.g.:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
double pi = 3.1415926535897932384626433832795028842, m = 2.66e-23, k =
1.38e-23;
double t, v, v2, dkt, result;
// check omitted
scanf("%lf %lf", &t, &v);
v2 = v * v;
dkt = 2 * k * t;
result = pow(m / (pi * dkt), 3 / 2.0) * 4 * pi * v2 * exp(-(m * v2) / (dkt));
printf("%.20g\n", result);
return 0;
}
The result from Pari/GP is 8.1246636077915008261803395870165527173e-9 and the result we get with the code above is 8.1246636077914841125e-09. Without the intermediate results v2, dkt and the replacement of sqrt we got 8.1246636077914824582e-09, not much of a difference, especially with accuracy where it gained nothing.
If you want the full 16 decimal digits of accuracy you need to take the whole thing apart and take a different approach.
replace
double pi=acos(-1.);
instead of
double pi=3.1415926535897932384626433832795028842;

casting signed to double different result than casting to float then double

So as part of an assignment I am working if a expression : (double) (float) x == (double) x
returns awlays 1 or not.(x is a signed integer)
it works for every value except for INT_MAX. I was wondering why is it so? if i print the values, they both show the same value,even for INT_MAX.
x = INT_MAX ;
printf("Signed X: %d\n",x);
float fx1 = (float)x;
double dx1 = (double)x;
double dfx = (double)(float)x;
printf("(double) x: %g\n",dx1);
printf("(float) x: %f \n",fx1);
printf("(double)(float)x: %g\n",dfx);
if((double) (float) x == (double) x){
printf("RESULT:%d\n", ((double)(float) x == (double) x));
}
EDIT: the entire program:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int main(int argc, char *argv[]){
//create random values
int x = INT_MAX ;
printf("Signed X: %d\n",x);
float fx1 = (float)x;
double dx1 = (double)x;
double dfx = (double)(float)x;
printf("(double) x: %g\n",dx1);
printf("(float) x: %f \n",fx1);
printf("(double)(float)x: %g\n",dfx);
if((double) (float) x == (double) x){
printf("RESULT:%d\n", ((double)(float) x == (double) x));
}
return 0;
}//end of main function
int and float have most likely the same number of bits in their representation, namely 32. float has a mantissa, an exponent and a sign bit, so the mantissa must have less than 31 bit, needed for the bigger int values like INT_MAX. So there loss of precision when storing in float.

Numerical Differentiation

How can I calculate the numerical second derivative of a function involving an exponential and a singularity at infinity. Unfortunately, the numerical derivative by Ridder's methods provided in "Numerical Recipes in C" can only calculate the first derivative (It requires analytical expression of the function beforehand.) Furthermore I have tried Chebyshev approximation and differentiating the function afterwards but the values given were way off the actual values. I have also tried some finite difference algorithms provided in a mathematical paper yet they were error prone too. The function is e^(x/2) / x^2. I would appreciate any help on the matter.
Thanks in advance
Latest Edit: The issue was solved the FADBAD libraries available in C++ did an extremely good job. They are available via http://www.fadbad.com/fadbad.html
EDIT:
// The compilation command used is given below
// gcc Q3.c nrutil.c DFRIDR.c -lm -o Q3
#include <stdio.h>
#include <math.h>
#include "nr.h"
#define LIM1 20.0
#define a -5.0
#define b 5.0
#define pre 100.0 // This defines the pre
/* This file calculates the func at given points, makes a
* plot. It also calculates the maximum and minimum of the func
* at given points and its first and second numerical derivative.
*/
float func(float x)
{
return exp(x / 2) / pow(x, 2);
}
int main(void)
{
FILE *fp = fopen("Q3data.dat", "w+"), *fp2 = fopen("Q3results.dat", "w+");
int i; // Declaring our loop variable
float x, y, min, max, err, nd1, nd2;
// Define the initial value of the func to be the minimum
min = func(0);
for(i = 0; x < LIM1 ; i++)
{
x = i / pre; // There is a singularity at x = 0
y = func(x);
if(y < min)
min = y;
fprintf(fp, "%f \t %f \n", x, y);
}
fprintf(fp, "\n\n");
max = 0;
for(i = 0, x = a; x < b; i++)
{
x = a + i / pre;
y = func(x);
nd1 = dfridr(func, x, 0.1, &err);
//nd2 = dfridr((*func), x, 0.1, &err);
fprintf(fp, "%f \t %f \t %f \t %f \n", x, y, nd1);
if(y > max)
max = y;
}
fprintf(fp2, "The minimum value of f(x) is %f when x is between 0 and 20. \n", min);
fprintf(fp2, "The maximum value of f(x) is %f when x is between -5 and 5. \n", max);
fclose(fp);
fclose(fp2);
return 0;
}
EDIT: Chebyshev
// The compilation command used is given below
//gcc Q3.c nrutil.c CHEBEV.c CHEBFT.c CHDER.c -lm -o Q3
#include <stdio.h>
#include <math.h>
#include "nr.h"
#define NVAL 150 // Degree of Chebyshev polynomial
#define LIM1 20.0
#define a -5.0
#define b 5.0
#define pre 100.0 // This defines the pre
/* This file calculates the func at given points, makes a
* plot. It also calculates the maximum and minimum of the func
* at given points and its first and second numerical derivative.
*/
float func(float x)
{
return exp(x / 2) / pow(x, 2);
}
int main(void)
{
FILE *fp = fopen("Q3data.dat", "w+"), *fp2 = fopen("Q3results.dat", "w+");
int i; // Declaring our loop variable
float x, y, min, max;
float nd1, nd2, c[NVAL], cder[NVAL], cder2[NVAL];
// Define the initial value of the func to be the minimum
min = func(0);
for(i = 0; x < LIM1 ; i++)
{
x = i / pre; // There is a singularity at x = 0
y = func(x);
if(y < min)
min = y;
fprintf(fp, "%f \t %f \n", x, y);
}
fprintf(fp, "\n\n");
max = 0;
// We make a Chebyshev approximation to our function our interval of interest
// The purpose is to calculate the derivatives easily
chebft(a,b,c,NVAL,func);
//Evaluate the derivatives
chder(a,b,c,cder,NVAL); // First order derivative
chder(a,b,cder,cder2,NVAL); // Second order derivative
for(i = 0, x = a; x < b; i++)
{
x = a + i / pre;
y = func(x);
nd1 = chebev(a,b,cder,NVAL,x);
nd2 = chebev(a,b,cder2,NVAL,x);
fprintf(fp, "%f \t %f \t %f \t %f \n", x, y, nd1, nd2);
if(y > max)
max = y;
}
fprintf(fp2, "The minimum value of f(x) is %f when x is between 0 and 20. \n", min);
fprintf(fp2, "The maximum value of f(x) is %f when x is between -5 and 5. \n", max);
fclose(fp);
fclose(fp2);
return 0;
}
That function is differentiable so using a numeric method is likely not the best. The second derivative is:
6*exp(x/2)/(x^4)-2*exp(x/2)/x^3 + exp(x/2)/(4*x^2)
The above can be simplified of course to speed up computation. Edit: had original formula wrong the first time.
If you want a 100% numeric approach then look at the numerical recipes for a cublic spline interpolation (Charter 3.3). It will give you the 2rd derivative at any location.
call spline() with x and y values to return the 2nd derivatives in y2. The second derivative varies linearly within each interval. So if for example you have
x y y2
0 10 -30
2 5 -15
4 -5 -10
then the 2nd derivative at x=1 is y2=-22.5 which is in-between -30 and -15.
you can also make a new splint() function to return the 2nd derivative a*y2a[i]+b*y2a[i+1]

Resources