|
|
View previous topic :: View next topic |
Author |
Message |
SBK Guest
|
Floating point rounding in CCS |
Posted: Sun Mar 23, 2003 1:14 pm |
|
|
How can I round floating point
numbers with certain numbers of
digits? For instance I need
a function like this:
float a,b;
a=20.54332;
b=round2(a);
( b=20.54)
I tried this but it seems it does not work:
int c;
float a,b;
a=20.54332;
c=a*100;
b=floor(c/100);
___________________________
This message was ported from CCS's old forum
Original Post ID: 12976 |
|
|
Steve H. Guest
|
Re: Floating point rounding in CCS |
Posted: Sun Mar 23, 2003 2:19 pm |
|
|
:=
:=I tried this but it seems it does not work:
:=
:= int c;
:= float a,b;
:=
:= a=20.54332;
:= c=a*100;
:= b=floor(c/100);
In the code above you took a float and multiplied it by an integer 100 and stuffed the result in an integer. That won't work at all on this C or the most expensive C+++++++ compiler.
If you are rounding for display just printf the required digits. If you are trying to round for accuracy in your program good luck - with the limited significant digits of the floats the very next operation will probably 'un-round' your result anyway.
Steve H.
___________________________
This message was ported from CCS's old forum
Original Post ID: 12978 |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
Re: Floating point rounding in CCS |
Posted: Sun Mar 23, 2003 3:24 pm |
|
|
CCS floating point numbers have a 23 bit mantissa. Any base 10 number that can be expressed as a power series of 2
a*2^22+b*2^21........2^0 where a,b,c .... have values of 0 or1 can be accurately represented. This includes all the whole numbers up to 2^23-1 but would not include 0.1 since it can't be expressed exactly. Note .5 or 1/2 is ok since all we have to do is subtract one from the exponent and see it as the whole number 1 ( base 2).
It is more to do with how numbers are represented in base 2 arithmetic verus the decimal system. For example 0.1 in decimal is expressable but in base 2 it doesn't neatly fit so an approximation is made. Simmilarly 1/3 can't be expressed exactly in the decimal system so we use .333333333333..... and stop at some point with an approximation. However 1/3 in base 3 arithmetic is a neat fit of 0.1. Some numbers such as pi have to be approximated no matter which base you use. A pocket calculator uses BCD so it never leaves base10 as did the early IBM computers. Binary is efficient but not all decimal numbers can be an exact fit.
___________________________
This message was ported from CCS's old forum
Original Post ID: 12981 |
|
|
R.J.Hamlett Guest
|
Re: Floating point rounding in CCS |
Posted: Sun Mar 23, 2003 4:16 pm |
|
|
:=
:=:=
:=:=I tried this but it seems it does not work:
:=:=
:=:= int c;
:=:= float a,b;
:=:=
:=:= a=20.54332;
:=:= c=a*100;
:=:= b=floor(c/100);
:=
:=In the code above you took a float and multiplied it by an integer 100 and stuffed the result in an integer. That won't work at all on this C or the most expensive C+++++++ compiler.
:=
Actually it will. In this case though the limit of the int at 255, will cause problems...
:=If you are rounding for display just printf the required digits. If you are trying to round for accuracy in your program good luck - with the limited significant digits of the floats the very next operation will probably 'un-round' your result anyway.
:=
The key is that the only way to give accurate results, is to shift away from the use of floats. You can give the sort of effect required like this:
void main() {
char store[8];
int ctr;
int flag;
float a;
a=20.54332;
flag=false;
sprintf(store,"\%05ld",(short int)((a*100)+0.005));
for (ctr=0;ctr<3;ctr++) {
if (store[ctr]!='0' || flag) {
putchar(store[ctr]);
flag=true;
}
else putchar(' ');
}
printf(".\%2s",&store[3]);
while (true) ;
}
If rounding is for accuracy, rather than just for the output, then the solution is to switch to using a scaled integer.
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12984 |
|
|
R.J.Hamlett Guest
|
Re: Floating point rounding in CCS |
Posted: Sun Mar 23, 2003 4:39 pm |
|
|
:=:=
:=:=:=
:=:=:=I tried this but it seems it does not work:
:=:=:=
:=:=:= int c;
:=:=:= float a,b;
:=:=:=
:=:=:= a=20.54332;
:=:=:= c=a*100;
:=:=:= b=floor(c/100);
:=:=
:=:=In the code above you took a float and multiplied it by an integer 100 and stuffed the result in an integer. That won't work at all on this C or the most expensive C+++++++ compiler.
:=:=
:=Actually it will. In this case though the limit of the int at 255, will cause problems...
:=
:=:=If you are rounding for display just printf the required digits. If you are trying to round for accuracy in your program good luck - with the limited significant digits of the floats the very next operation will probably 'un-round' your result anyway.
:=:=
:=
:=The key is that the only way to give accurate results, is to shift away from the use of floats. You can give the sort of effect required like this:
:=
:=void main() {
:= char store[8];
:= int ctr;
:= int flag;
:= float a;
:= a=20.54332;
:= flag=false;
:= sprintf(store,"\%05ld",(short int)((a*100)+0.005));
:= for (ctr=0;ctr<3;ctr++) {
:= if (store[ctr]!='0' || flag) {
:= putchar(store[ctr]);
:= flag=true;
:= }
:= else putchar(' ');
:= }
:= printf(".\%2s",&store[3]);
:= while (true) ;
:=}
:=
:=If rounding is for accuracy, rather than just for the output, then the solution is to switch to using a scaled integer.
:=
:=Best Wishes
Change the 'short int' to int16 in the above. I forgot to reset this after checking the code worked in a normal C...
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12985 |
|
|
Steve H. Guest
|
Oops! Thanks.... |
Posted: Sun Mar 23, 2003 11:56 pm |
|
|
>>Actually it will. In this case though the limit of the int
>> 255, will cause problems...
Oops, my bad! You are right, K&R says that floats are converted to ints in standard C.
Thanks for correcting this for me....
:-)
In CCS - I have noticed that explicit casting must be done and that in the 2.6x version that I use the compiler won't cast correctly unless explicitly told to.
Steve H.
___________________________
This message was ported from CCS's old forum
Original Post ID: 12991 |
|
|
R.J.Hamlett Guest
|
Re: Oops! Thanks.... |
Posted: Mon Mar 24, 2003 3:11 am |
|
|
:=>>Actually it will. In this case though the limit of the int
:=>> 255, will cause problems...
:=
:=Oops, my bad! You are right, K&R says that floats are converted to ints in standard C.
:=
:=Thanks for correcting this for me....
:=
:=:-)
:=
:=In CCS - I have noticed that explicit casting must be done and that in the 2.6x version that I use the compiler won't cast correctly unless explicitly told to.
:=
It is variable. Some things will convert OK, but if you look through the past posts, you will find a lot of advice (including posts from me), saying that manual casting avoids a lot of problems in CCS C. Basically if you are doing mixed type maths, it is better to not rely on the implicit casts. As you say, the results and effects do vary from version to version.
It has the (slight) advantage, of making you think about what maths type is involved in a particular operation, but is one of the biggest 'fundamental' differences between the CCS C, and a normal compiler...
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12993 |
|
|
Steve H Guest
|
Right.... |
Posted: Mon Mar 24, 2003 1:49 pm |
|
|
Right, I've had problems with intermediate overflow when doing something like this,
int a;
long b,c;
c = a * b; // Can / will overflow when doing the multiply
c = (long)a * b; // Works fine!
So I cast everything with CCS now!
___________________________
This message was ported from CCS's old forum
Original Post ID: 13017 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|