Can't round number to two decimal places using floorf - c

I found this formula here:
podrucje[i][j] = floorf(podrucje[i][j] * 100 + 0.5)/100;
where podrucje[][] is float matrix. floorf returns correct value (desired * 100) but problem is with /100. For example if I have 49.599998, floorf returns 4960.000 and after dividing by 100 result is again 49.599998.
Where is the problem?
I know I can round it while printing but I'm going to use this matrix in Excel where it is converted to range thus i can't influence on representation.

Most decimal numbers aren't exactly representable as floats.
You probably need to either store them as integers, or do the rounding when converting to something humanly visible (i.e. printing the number out).
If you want to use the number for further calculations and need it to be rounded first, use a different representation.

This is a fundamental problem with the representation of floating point arithmetic which is not base-10! You can print a base-10 with rounding to 2 decimal places though.
The standard safe way to export numbers safely across boundaries is through plain text ascii rather than as binary.

Related

printf behaviour in C

I am trying to understand what is the difference between the following:
printf("%f",4.567f);
printf("%f",4.567);
How does using the f suffix change/influence the output?
How using the 'f' changes/influences the output?
The f at the end of a floating point constant determines the type and can affect the value.
4.567 is floating point constant of type and precision of double. A double can represent exactly typical about 264 different values. 4.567 is not one on them*1. The closest alternative typically is exactly
4.56700000000000017053025658242404460906982421875 // best
4.56699999999999928235183688229881227016448974609375 // next best double
4.567f is floating point constant of type and precision of float. A float can represent exactly typical about 232 different values. 4.567 is not one on them. The closest alternative typically is exactly
4.566999912261962890625 // best
4.56700038909912109375 // next best float
When passed to printf() as part of the ... augments, a float is converted to double with the same value.
So the question becomes what is the expected difference in printing?
printf("%f",4.56700000000000017053025658242404460906982421875);
printf("%f",4.566999912261962890625);
Since the default number of digits after the decimal point to print for "%f" is 6, the output for both rounds to:
4.567000
To see a difference, print with more precision or try 4.567e10, 4.567e10f.
45670000000.000000 // double
45669998592.000000 // float
Your output may slightly differ to to quality of implementation issues.
*1 C supports many floating point encodings. A common one is binary64. Thus typical floating-point values are encoded as an sign * binary fraction * 2exponent. Even simple decimal values like 0.1 can not be represented exactly as such.

Can you round a value to 2 decimal places in C?

I am calculating the volume of a room and I got a number with 6 decimal places. I was wondering if I can reduce the value to only 2 decimal places. The resulting number for the volume is from 5 different variables, which I do not know if it matters in this situation.
#Rashmi solution provides a nicely rounded display of a floating point value.
It does not change the value of the original number.
If one wants to round a floating point value to the nearest 0.01 use round()
#include <math.h>
double d = 1.2345;
d = round(d * 100.0)/100.0;
Notes:
Due to FP limitations, the rounded value may not be exactly a multiple of 0.01, but will be the closest FP number a given platform allows.
When d is very close to x.xx5, (x is various digits 0-9) d * 100.0 introduces a rounding in the product before the round() call. Code may round the wrong way.
You can use printf("%.2f", 20.233232)
There might be a round() function floating around (ha ha) somewhere in some math library (I don't have a C ref at hand). If not, a quick and dirty method would be to multiply the number by 100 (shift decimal point right by 2), add 0.5, truncate to integer, and divide by 100 (shift decimal point left by 2).
The floating point value 0.01 cannot be expressed in IEEE 754, so you still get more decimals than you asked for.
Better Way: just don't display the extra decimals in your program. I doubt you are "getting" 6 decimals; it could be the default value for a plain
printf ("too much accuracy in %f!", yourFloat);
If so, use %.2f to display.
Slightly Worse Way, depending on the numerical range and the sort of calculations you are going to do: multiply the floats by 100, round, and store as integer. 100.00% guaranteed you'll only get two digits of accuracy. Watch out when dividing (you'll loose 2 digits if not done carefully) and multiplying (you'll gain 2).

recurring binary for decimal number [duplicate]

This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 9 years ago.
float a;
a=8.3;
if(a==8.3)
printf("1");
else
printf("2");
giving a as 8.3 and 8.4 respectively and comparing with 8.3 and 8.4 correspondingly , output becomes 2 but when comparing with 8.5 output is 1. I found that it is related to concept of recurring binary which takes 8 bytes. I want to know how to find which number is recurring binary. kindly give some input.
Recurring numbers are not representable, hence floating point comparison will not work.
Floating point math is not exact. Simple values like 0.2 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Also as in the 2nd comment - floating point literals 8.3 has type double and a has type float.
Comparing with epsilon – absolute error
Since floating point calculations involve a bit of uncertainty we can try to allow for this by seeing if two numbers are ‘close’ to each other. If you decide – based on error analysis, testing, or a wild guess – that the result should always be within 0.00001 of the expected result then you can change your comparison to this:
if (fabs(result - expectedResult) < 0.00001)
For example, 3/7 is a repeating binary fraction, its computed value in double precision is different from its stored value in single precision. Thus the comparison 3/7 with its stored computed value fails.
For more please read - What Every Computer Scientist Should Know About Floating-Point Arithmetic
You should not compare floating point numbers for equality using ==. Because of how floating point numbers are actually stored in memory it will give inaccurate results.
Use something like this to determine if your number a is close enough to the desired value:
if(fabs(a-8.3) < 0.0000005))
There are two problems here.
First is that floating point literals like 8.3 have type double, while a has type float. Doubles and floats store values to different precisions, and for values that don't have an exact floating point representation (such as 8.3), the stored values are slightly different. Thus, the comparison fails.
You could fix this by writing the comparison as a==8.3f; the f suffix forces the literal to be a float instead of a double.
However, it's bad juju to compare floating point values directly; again, most values cannot be represented exactly, but only to an approximation. If a were the result of an expression involving multiple floating-point calcuations, it may not be equivalent to 8.3f. Ideally, you should look at the difference between the two values, and if it's less than some threshold, then they are effectively equivalent:
if ( fabs( a - 8.3f) < EPSILON )
{
// a is "equal enough" to 8.3
}
The exact value of EPSILON depends on a number of factors, not least of which is the magnitude of the values being compared. You only have so many digits of precision, so if the values you're trying to compare are greater than 999999.0, then you can't test for differences within 0.000001 of each other.

How can I round a float to a given decimal precision

I need to convert a floating-point number with system precision to one with a specified precision (e.g. 3 decimal places) for the printed output. The fprintf function will not suffice for this as it will not correctly round some numbers. All the other solutions I've tried fail in that they all reintroduce undesired precision when I convert back to a float. For example:
float xf_round1_f(float input, int prec) {
printf("%f\t",input);
int trunc = round(input * pow(10, prec));
printf("%f\t",(float)trunc);
input=(float)trunc / pow(10, prec);
printf("%f\n",input);
return (input);
}
This function prints the input, the truncated integer and the output to each line, and the result looks like this for some numbers supposed to be truncated to 3 decimal places:
49.975002 49975.000000 49.974998
49.980000 49980.000000 49.980000
49.985001 49985.000000 49.985001
49.990002 49990.000000 49.990002
49.995003 49995.000000 49.994999
50.000000 50000.000000 50.000000
You can see that the second step works as intended - even when "trunc" is cast to float for printing - but as soon as I convert it back to a float the precision returns. The 1st and 6th rows illustrate problem cases.
Surely there must be a way of resolving this - even if the 1st row result remained 49.975002 a formatted print would give the desired effect, but in this case there is a real problem.
Any solutions?
Binary floating-point cannot represent most decimal numerals exactly. Each binary floating-point number is formed by multiplying an integer by a power of two. For the common implementation of float, IEEE-754 32-bit binary floating-point, that integer must be in (–224, 224). There is no integer x and integer y such that x•2y exactly equals 49.975. Therefore, when you divide 49975 by 1000, the result must be an approximation.
If you merely need to format a number for output, you can do this with the usual fprintf format specifiers. If you need to compute exactly with such numbers, you may be able to do it by scaling them to representable values and doing the arithmetic either in floating-point or in integer arithmetic, depending on your needs.
Edit: it appears you may only care about the printed results. printf is generally smart enough to do proper rounding to the number of digits you specify. If you give a format of "%.3f" you will probably get what you need.
If your only problem is with the cases that are below the desired number, you can easily fix it by making everything higher than the desired number instead. Unfortunately this increases the absolute error of the answer; even a result that was exact before, such as 50.000 is now off.
Simply add this line to the end of the function:
input=nextafterf(input, input*1.0001);
See it in action at http://ideone.com/iHNTzs
49.975002 49975.000000 49.974998 49.975002
49.980000 49980.000000 49.980000 49.980003
49.985001 49985.000000 49.985001 49.985004
49.990002 49990.000000 49.990002 49.990005
49.995003 49995.000000 49.994999 49.995003
50.000000 50000.000000 50.000000 50.000004
If you require exact representation of all decimal fractions with three digits after the decimal point, you can work in thousandths. Use an integer data type to represent one thousand times the actual number for all intermediate results.
Fixed point numbers. That is where you keep the actual numbers in a wide precision integer format, for example long or long long. And you also keep the number of decimal places. And then you will also need methods to scale the fixed point number by the decimal places. And some way to convert to/from strings.
The reason why you are having trouble that 1/10 is not representable exactly as a fractional power of 2 (1/2, 1/4, 1/8, etc). This is the same reason that 1/3 is a repeating decimal in base 10 (0.33333...).

Without using libraries, how can I round a floating point number to two places in C?

I am learning about Operating System programming and I need to assume I have few resources.
Then how should I, for example, compute 2 / 3 and truncate that to two decimal places? Are there any math algorithms or bit manipulation tricks I can possibly use?
You can't round floating point number to base 10 two places or any number of base 10 places, floating point numbers are just approximations. There are lots of base 10 number which just can not be represented exactly as base 2 number with a finite number of decimal places, this is for the exact same reason you can not represent the number 1/3 in base 10 with a finite number of decimal places. You should either treat you float as approximations and then only round as part of your display. Or if you don't want approximation then do something like use integer to represents 1/100ths and then divide them by 100 to get you value to display.
If you're not going to manipulate the variable (just print it), also you can use:
printf("%.2f\n", 2.f / 3);
Round to two decimal places: multiply by 100, convert to integer, divide by 100.0 (although note that you can't say in general a floating point number, in its native representation, has exactly two base-ten digits after the decimal point; those need not be round numbers in native representation.)
For that reason - I would actually argue that multiplying by 100, and storing as an integer with the understanding that this represents 100ths of a unit, is a more accurate way to represent a "number accurate to two decimal places".
// this is an old trick from BASIC
// multiply by 100.0 and add 0.5 (the 0.5 is for the rounding)
// normally you want to round rather than truncate for a more accurate result
// take the integer value of this to get rid of additional decimal places
// then divide by 100.0 to get the original number back only rounded
// of course you need to use floating point
#include <stdio.h>
#include <stdlib.h>
int main()
{
double a=1.0, b=2.0, c=3.0;
a = (int)((b/c)*100.0+0.5)/100.0;
printf("%f\n",a); // print all digits of a
printf("%10.2f\n",a); // print only 2 decimal points of a
return 0;
}
One of my strategies is to multiply the floating point number (such as 2 / 3) by (10 ^ precision) and truncating it by casting to int.

Resources