I am coding a graphical program in C and my cartesian values are in between [-1,1], I am having trouble rounding off values so that I can use them for plotting and further calculations. I know how to round values greater than 1 with decimals but this I haven't done before.
So how would I go about rounding values? For example,
.7213=.7
.7725= .8
.3666667=.4
.25=.2 or .3
.24=.2
Any suggestions would be gladly appreciated. :)
You don't (and can't, to any high degree of accuracy, due to how floating point values are stored) round floating point values, you can only output them to different degrees of precision. If you wanted all your float values rounded to 1 decimal place before using them in calculations, then do your calculations with integers, with everything multiplied by 10, then divide by 10 just before you display it.
In most languages, people often implement such rounding in an ad hoc way using *10, integral rounding, and /10. For example:
$ cat round.c
#include <stdio.h>
#include <stdint.h>
int main()
{
fprintf(stderr, "%f\n", ((double) ((uint64_t) (10*0.7777))) / 10);
return 0;
}
$ gcc round.c
[tommd#Vodka Test]$ ./a.out
0.700000
Related
While running the following lines of code:
int i,a;
for(i=0;i<=4;i++)
{
a=pow(10,i);
printf("%d\t",a);
}
I was surprised to see the output, it comes out to be 1 10 99 1000 9999 instead of 1 10 100 1000 10000.
What could be the possible reason?
Note
If you think it's a floating point inaccuracy that in the above for loop when i = 2, the values stored in variable a is 99.
But if you write instead
a=pow(10,2);
now the value of a comes out to be 100. How is that possible?
You have set a to be an int. pow() generates a floating point number, that in SOME cases may be just a hair less than 100 or 10000 (as we see here.)
Then you stuff that into the integer, which TRUNCATES to an integer. So you lose that fractional part. Oops. If you really needed an integer result, round may be a better way to do that operation.
Be careful even there, as for large enough powers, the error may actually be large enough to still cause a failure, giving you something you don't expect. Remember that floating point numbers only carry so much precision.
The function pow() returns a double. You're assigning it to variable a, of type int. Doing that doesn't "round off" the floating point value, it truncates it. So pow() is returning something like 99.99999... for 10^2, and then you're just throwing away the .9999... part. Better to say a = round(pow(10, i)).
This is to do with floating point inaccuracy. Although you are passing in ints they are being implicitly converted to a floating point type since the pow function is only defined for floating point parameters.
Mathematically, the integer power of an integer is an integer.
In a good quality pow() routine this specific calculation should NOT produce any round-off errors. I ran your code on Eclipse/Microsoft C and got the following output:
1 10 100 1000 10000
This test does NOT indicate if Microsoft is using floats and rounding or if they are detecting the type of your numbers and choosing the appropriate method.
So, I ran the following code:
#include <stdio.h>
#include <math.h>
main ()
{
double i,a;
for(i=0.0; i <= 4.0 ;i++)
{
a=pow(10,i);
printf("%lf\t",a);
}
}
And got the following output:
1.000000 10.000000 100.000000 1000.000000 10000.000000
No one spelt out how to actually do it correctly - instead of pow function, just have a variable that tracks the current power:
int i, a, power;
for (i = 0, a = 1; i <= 4; i++, a *= 10) {
printf("%d\t",a);
}
This continuing multiplication by ten is guaranteed to give you the correct answer, and quite OK (and much better than pow, even if it were giving the correct results) for tasks like converting decimal strings into integers.
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).
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.
I have 2 doubles x and y. When I divide x/y I dont get the result I am hoping to get.
Here is the printf command I am using in c and the output I am getting:
command:
printf("%3.10f %3.2f %3.12f %d\n",x,y,x/y,(int)(x/y));
output:
1.0000000000 0.10 10.000000000000 9
To me, x/y ought to be 10 and so not sure why (int)(x/y) is producing 9 instead of 10.
Can someone help me understand this surce of this problem please?
x/y results in slightly less than 10 (it surely is less than 10^-12 off, otherwise the other result wouldn't show as 10.000000000000), probably due to the usual floating point math rounding errors.
The printf performs rounding to the digit of the requested precision, but the conversion to int is a brutal truncation, thus, even if it's 9.99999999999999... you get 9 as a result.
This happens because you are truncating the decimal part. Round it, and you should be fine.
printf("%3.10f %3.2f %3.12f %d\n",x,y,x/y,round(x/y));
casting to int doesn't round a double to the nearest integer.
Look at round() for float in C++ for details
I'm doing some trigonometry calculations in C/C++ and am running into problems with rounding errors. For example, on my Linux system:
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[]) {
printf("%e\n", sin(M_PI));
return 0;
}
This program gives the following output:
1.224647e-16
when the correct answer is of course 0.
How much rounding error can I expect when using trig functions? How can I best handle that error? I'm familiar with the Units in Last Place technique for comparing floating point numbers, from Bruce Dawson's Comparing Floating Point Numbers, but that doesn't seem to work here, since 0 and 1.22e-16 are quite a few ULPs apart.
The answer is only 0 for sin(pi) - did you include all the digits of Pi ?
-Has anyone else noticed a distinct lack of, irony/sense of humour around here?
An IEEE double stores 52 bits of mantissa, with the "implicit leading
one" forming a 53 bit number. An error in the bottom bit of a result
therefore makes up about 1/2^53 of the scale of the numbers. Your output is
of the same order as 1.0, so that comes out to just about exactly one
part in 10^16 (because 53*log(2)/log(10) == 15.9).
So yes. This is about the limit of the precision you can expect. I'm
not sure what the ULP technique you're using is, but I suspect you're
applying it wrong.
Sine of π is 0.0.
Sine of M_PI is about 1.224647e-16.
M_PI is not π.
program gives ... 1.224647e-16 when the correct answer is of course 0.
Code gave a correct answer to 7 significant places.
The following does not print the sine of π. It prints the sine of a number close to π. See below pic.
π // 3.141592653589793 2384626433832795...
printf("%.21\n", M_PI); // 3.141592653589793 115998
printf("%.21f\n", sin(M_PI));// 0.000000000000000 122465
Note: With the math function sine(x), the slope of the curve is -1.0 at x = π. The difference of π and M_PI is about the sin(M_PI) - as expected.
am running into problems with rounding errors
The rounding problem occurs when using M_PI to represent π. M_PI is the double constant closest to π, yet since π is irrational and all finite double are rational, they must differ - even by a small amount. So not a direct rounding issue with sin(), cos(), tan(). sin(M_PI) simple exposed the issue started with using M_PI - an inexact π.
This problem, with different non-zero results of sin(M_PI), occurs if code used a different FP type like float, long double or double with something other than 53 binary bits of precision. This is not a precision issue so much as a irrational/rational one.
#Josh Kelley - ok serious answer.
In general you should never compare the results of any operation involving floats or doubles with each other.
The only exceptions is assignment.
float a=10.0;
float b=10.0;
then a==b
Otherwise you always have to write some function like bool IsClose(float a,float b, float error) to allow you to check if two numbers are within 'error' of each other.
Remember to also check signs/use fabs - you could have -1.224647e-16
There are two sources of error. The sin() function and the approximated value of M_PI. Even if the sin() function were 'perfect', it would not return zero unless the value of M_PI were also perfect - which it is not.
I rather think that will be system-dependent. I don't think the Standard has anything to say on how accurate the transcendental functions will be. Unfortunately, I don't remember seeing any discussion of function precision, so you'll probably have to figure it out yourself.
Unless your program requires significant digits out to the 16th decimal place or more, you probably can do the rounding manually. From my experience programming games we always rounded our decimals to a tolerable significant digit. For example:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define HALF 0.5
#define GREATER_EQUAL_HALF(X) (X) >= HALF
double const M_PI = 2 * acos(0.0);
double round(double val, unsigned places = 1)
{
val = val * pow(10.0f, (float)places);
long longval = (long)val;
if ( GREATER_EQUAL_HALF(val - longval) ) {
return ceil(val) / pow(10.0f, (float)places);
} else {
return floor(val) / pow(10.0f, (float)places);
}
}
int main()
{
printf("\nValue %lf", round(sin(M_PI), 10));
return 0;
}
I get the exact same result on my system - I'd say it is close enough
I would solve the problem by changing the format string to "%f\n" :)
However, this gives you a "better" result, or at least on my system it does give -3.661369e-245
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[]) {
printf("%e\n", (long double)sin(M_PI));
return 0;
}
Maybe too low accuracy of implementation
M_PI = 3.14159265358979323846 (M_PI is not π)
http://fresh2refresh.com/c/c-function/c-math-h-library-functions/
It is an inaccuracy in implementation, see Stephen C. Steel's comment under Andy Ross` answer above and chux's answer.