Declare float variable to only contain 3 decimal places - c

Is this even possible? i tried to google it but i cant seem to find the right answer.
I need to limit the decimal places since the answer will really differ if there is only 3 decimal places than 5, so i was hoping that you could help me with these. i know how to print with 3 decimal places but to declare a variable to only hold 3 decimal places is something i do not know. i could also use some links if you have any.
float sinfa(float num1)
{
float fc;
float powers;
float rad_angle;
rad_angle = num1 * (PI / 180.0);
powers = pow(num1,4);
fc = sin(rad_angle)-powers+1;
return (fc);
}
float sinfb(float num2)
{
float fd;
float powerss;
float rad_angle1;
rad_angle1 = num2 * (PI / 180.0);
powerss = pow(num2,4);
fd = sin(rad_angle1)-powerss+1;
return (fd);
}
float tp(float fa,float fb,float num1,float num2)
{
float p;
float fm2 = fa*num2;
float fm1 = fb*num1;
p = (fm2-fm1)/(fa-fb);
return (p);
}
float sinp(float p1)
{
float fop;
float ppowers;
float rad_angle2;
rad_angle2 = p1 * (PI / 180.0);
ppowers = pow(p1,4);
fop = sin(rad_angle2)-ppowers+1;
return (fop);
}
Thank you

Can't be done. A float is a 32-bit floating-point value in every C compiler I have ever used. There is nothing standard in the language to redefine how it works.
You could write a set of fixed-point functions that store values multiplied by 1000, or use a general library that implements fixed-point with arbitrary precision and set the precision to 3 decimal digits.
C++ fixed point library?

It can be done!
int intVal = 1.234567 * 1000; // result: 1234
float floatVal = (float)intVal / 1000; // result: 1.234
The trick is to:
Move the required number of digits to the left-hand side of the decimal place.
Truncate all the digits on the right-hand side of the decimal place.
Move the required number of digits back to the right-hand side of the decimal place.

Related

Round 37.1-28.75 float calculation correctly to 8.4 instead of 8.3

I have problem with floating point rounding. I want to calculate floating point numbers and round them to (given) N decimals. In this example I want to round to 1 decimal places.
Calculation 37.1-28.75 will result into floating point 8.349998 (instead of 8.35), which will result printf rounding to 8.3 instead of 8.4 for 1 decimal places.
The actual result in math is 37.10-28.75=8.35000000, but due to floating point imprecision it is converted into 8.349998, which is then converted into 8.3 instead of 8.4 when using 1 decimal place rounding.
Minimum reproducible example:
float a = 37.10;
float b = 28.75;
//a-b = 8.35 = 8.4
printf("%.1f\n", a - b); //outputs 8.3 instead of 8.4
Is it valid to add following to the result:
float result = a - b;
if (result > 0.0f)
{
result += powf(10, -nr_of_decimals - 1) / 2;
}
else
{
result -= powf(10, -nr_of_decimals - 1) / 2;
}
EDIT: corrected that I want 1 decimal place rounded output, not 2 decimal places
EDIT2: negative results are needed as well (28.75-37.1 = -8.4)
On my system I do actually get 8.35. It's possible that you have to set the rounding direction to "nearest" first, try this (compile with e.g. gcc ... -lm):
#include <fenv.h>
#include <stdio.h>
int main()
{
float a = 37.10;
float b = 28.75;
float res = a - b;
fesetround(FE_TONEAREST);
printf("%.2f\n", res);
}
Binary floating point is, after all, binary, and if you do care about the correct decimal rounding this much, then your choices would be:
decimal floating point, or
fixed point.
I'd say the solution is to use fixed point, especially if you're on embedded, and forget about everything else.
With
int32_t a = 3710;
int32_t b = 2875;
the result of
a - b
will exactly be
835
every time; and then you just need to have a simple fixed point printing routine for the desired precision, and check the following digit after the last digit to see if it needs to be rounded up.
If you want to round to 2 decimals, you can add 0.005 to the result and then offset it with floorf:
float f = 37.10f - 28.75f;
float r = floorf((f + 0.005f) * 100.f) / 100.f;
printf("%f\n", r);
The output is 8.350000
Why are you using floats instead of doubles?
Regarding your question:
Is it valid to add following to the result:
float result = a - b;
if (result > 0.0f)
{
result += powf(10, -nr_of_decimals - 1) / 2;
}
else
{
result -= powf(10, -nr_of_decimals - 1) / 2;
}
It doesn't seem so, on my computer I get 8.350498 instead of 8.350000.
After your edit:
Calculation 37.1-28.75 will result into floating point 8.349998, which will result printf rounding to 8.3 instead of 8.4.
Then
float r = roundf((f + (f < 0.f ? -0.05f : +0.05f)) * 10.f) / 10.f;
is what you are looking for.

How to set the level of precision for the decimal expansion of a rational number

I'm trying to print out the decimal expansion of a rational number in C. The problem I have is that when I divide the numerator by the denominator I lose precision. C rounds up the repeating part when I don't want it to.
For example, 1562/4995 = 0.3127127127... but in my program I get 1562/4995 = 0.312713. As you can see a part of the number that I need has been lost.
Is there a way to specify C to preserve a higher level of decimal precision?
I have tried to declare the result as a double, long double and float. I also tried to split the expansion into 2 integers seperated by a '.'
However both methods haven't been successful.
int main() {
int numerator, denominator;
numerator = 1562;
denominator = 4995;
double result;
result = (double) numerator / (double) denominator;
printf("%f\n", result);
return 0;
}
I expected the output to be 1562/4995 = 0.3127127127... but the actual output is 1562/4995 = 0.312713
The %f format specifier to printf shows 6 digits after the decimal point by default. If you want to show more digits, use a precision specifier:
printf("%.10f\n", result);
Also, the double type can only accurately store roughly 16 decimal digits of precision.
You need to change your output format, like this:
printf("%.10lf\n", result);
Note two things:
The value after the . specifies the decimal precision required (10 decimal places, here).
Note that I have added an l before the f to explicitly state that the argument is a double rather than a (single-precision) float.
EDIT: Note that, for the printf function, it is not strictly necessary to include the l modifier. However, when you come to use the 'corresponding' scanf function for input, it's absence will generate a warning and (probably) undefined behaviour:
scanf("%f", &result); // Not correct
scanf("%lf", &result); // Correct
If printing is all you want to do, you can do this with the same long division you were taught in elementary school:
#include <stdio.h>
/* Print the decimal representation of N/D with up to
P digits after the decimal point.
*/
#define P 60
static void PrintDecimal(unsigned N, unsigned D)
{
// Print the integer portion.
printf("%u.", N/D);
// Take the remainder.
N %= D;
for (int i = 0; i < P && N; ++i)
{
// Move to next digit position and print next digit.
N *= 10;
printf("%u", N/D);
// Take the remainder.
N %= D;
}
}
int main(void)
{
PrintDecimal(1562, 4995);
putchar('\n');
}

Why 5.0/3 is 1.666667 in C?

I'm new in C language, but I've tried integer, float and double division in C as I'm normally doing in Java, but when I execute 5.0/3 instead of 1.6666666666666667 I'm getting 1.666667 for double division and for float division.
I had tried to execute the program using Visual Studio as I always do but I got the message "First number is 1, second one is 1.666667 and the last one is 1.666667." after executing:
#include <stdio.h>
int main()
{
int firstNumber = 5 / 3;
float secondNumber = 5.0f / 3.0f;
double thirdNumber = 5.0 / 3.0;
printf("First number is %d, second one is %f and the last one is %lf.", firstNumber, secondNumber, thirdNumber);
return 0;
}
Why I'm getting the same result for 'secondNumber' and for 'thirdNumber'?
Typical float can represent about 232 different values.
Typical double can represent about 264 different values.
In both types, 5/3, the exact quotient of the division, is not in that set. Instead a nearby value (some binary fraction) is used.
float secondNumber = 5.0f / 3.0f; // 1.66666662693023681640625
double thirdNumber = 5.0 / 3.0; // 1.6666666666666667406815349750104360282421112060546875
When using "%f", 6 places past the decimal point are used. The printed text is a rounded one. In both cases, rounding to the same.
1.666667
To see more digits, use "%.10f", "%.20f", etc. #xing
printf("%.10f\n", secondNumber);
printf("%.10f\n", thirdNumber);
Output
1.6666666269
1.6666666667

How do I write only the decimal places in C language?

If I have 2.55, how do I write only .55 and skip 2 in programming language?
Well you can do this to store it in another variable -
double a=2.55,b;
b =a-(long)a; // subtracting decimal part from a
printf("%.2f\n",b);
As pointed out by Mark Dickinson Sir in comment that this is not safe . So you can make use of function modf from <math.h>-
For example -
double a=-2.55,b,i;
b =modf(a,&i); // i will give integer part and b will give fraction part
printf("%.2f\n",b);
Use double modf(double value, double *iptr) to get the factional part. Use round() to get the best value near the requested precision.
double GetDecimalPlaces(double x, unsigned places) {
double ipart;
double fraction = modf(x, &ipart);
return fraction;
// or
double scale = pow(10.0, places);
return round(fraction * scale)/scale;
}
void GetDecimalPlaces_Test(double x, unsigned places) {
printf("x:%e places:%u -->", x, places);
printf("%#.*f\n", places, GetDecimalPlaces(x, places));
// Additional work needed if leading '0' is not desired.
}
int main(void) {
GetDecimalPlaces_Test(2.55, 2);
GetDecimalPlaces_Test(-2.55, 2);
GetDecimalPlaces_Test(2.05, 2);
GetDecimalPlaces_Test(0.0, 2);
GetDecimalPlaces_Test(0.0005, 2);
}
Output
x:2.550000e+00 places:2 -->0.55
x:-2.550000e+00 places:2 -->-0.55
x:2.050000e+00 places:2 -->0.05
x:0.000000e+00 places:2 -->0.00
x:5.000000e-04 places:2 -->0.00
One dirty trick is to cast your double to an int to get only the whole number. You can then subtract the two to get only the decimal part:
double d = 2.55;
double remainder = d - (int)d;
printf ("%.2f\n", remainder);
double values are not perfectly precise, so small rounding errors can get introduced. You can store the total number in an Integer. You can for example divide by 100 to get the value before the . and use % modulus to get the decimal values.
Example:
int main()
{
int num = 255;
printf("%d.%d\n", num / 100, num % 100); // prints 2.55
printf(".%d", num % 100); // prints .55
return 0;
}
This fails with negative numbers, but you can easily add cases to handle that.

Floating point in C

I am asking a user for two non-negative integer values in C. I then want to convert these to percentages (expressed as decimals). Unfortunately, my floats are coming up as zeroes. Why is this, and how do I fix it?
int a = 5;
int b = 10;
int total = a + b;
float a_percent = a / total;
float b_percent = b / total;
printf("%.2f, %.2f\n", a_percent, b_percent);
You aren't using floats, you're using integers, and so the integral division gives zero (which is then assigned to a float).
To perform a floating-point operation, you must first convert the integers (or at least one of them) to a float. Conveniently, we just use total:
float total = a + b; // exact
float ap = a / total;
float bp = b / total; // OK, these are now floating-point operations
In addition to the problems others have pointed out, the ratio won't be a percentage until you multiply it by 100.0.
An int divided by an int will always return an int. You'll have to make one of the two arguments a float before dividing:
float a_percent = (float) a / total;
float b_percent = (float) b / total;
I am not a C expert, but my guess is because dividing an int by an int always results in an int.
You may need to do something like this:
float a_percent = (float)a/total;
float b_percent = (float)b/total;
You're first performing an integer division, then converting the result to floating point. This will not give the results you want. Either make total a floating point value to begin with (so that the types get automatically promoted right) or cast a and b to (float) before performing the division.
You are using integer math not floating point here.
Try:
float a_percent = a/(float)total;
float b_percent = b/(float)total;
For a simple percentage you may be happier using fixed-point. Just multiply your numerator (a or b) by 100 and you'll get the percentage from the division. forex:
int a = 5;
int b = 10;
int total = a + b;
int a_percent = 100*a/total;
int b_percent = 100*b/total;
printf("a%%=%d, b%%=d\n", a_percent, b_percent);

Resources