![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
hayee
Joined: 05 Sep 2007 Posts: 252
|
break float number to get separate numbers. |
Posted: Thu Jun 17, 2010 7:25 am |
|
|
Hi,
I have a floating number, suppose 55.96, and I want to store each digit in an integer variable like value1=5, value2=5, value3=9, value4=6.
Can someone tell me how I can break the floating number to get separate numbers. |
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Thu Jun 17, 2010 7:30 am |
|
|
Code: | int8 huns, tens, ones, tenths, hundredths;
float number;
huns = (int8) (number / 100);
tens = (int8) ((number / 10) % 10);
ones = (int8) ((number % 100) % 10); |
...etc etc etc |
|
![](templates/subSilver/images/spacer.gif) |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Thu Jun 17, 2010 7:40 am |
|
|
What about the values after point (9 and 6).
How do I get them? |
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Thu Jun 17, 2010 8:37 am |
|
|
Multiply by 10 and extract the "one", which is actually the tenth. Repeat to extract the hundredth. |
|
![](templates/subSilver/images/spacer.gif) |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Thu Jun 17, 2010 11:43 pm |
|
|
I am getting error on this line
Code: |
tens=(int8)((total_rs/10)%10);
|
Error is : only integers are supported for this operation.
I have declared tens as an int8 and total_rs as an float. |
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Fri Jun 18, 2010 7:10 am |
|
|
Do the cast to an int first.
Code: | int16 int_total_rs;
int8 tens;
float total_rs;
int_total_rs = (int16) total_rs;
tens = (int8)((int_total_rs/10)%10); |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Fri Jun 18, 2010 8:38 am |
|
|
To optimise a little, it is perhaps worth using some of the other functions.
1) Integer arithmetic is far more efficient than 'float'. Typically it takes about 4* the machine cycles to do a float division, compared to an int16.
2) If you start with the number *100, then divide by ten, you get two terms in one operation, if you use the 'div' operator, rather than /.
So:
Code: |
ldiv_t lidivval;
int8 digits[4];
float starting_val;
ldivval=ldiv((signed int16)(starting_val*100),10);
digits[3]=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
digits[2]=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
digits[1]=ldivval.rem;
digits[0]=ldivval.quot;
|
By no means the best possible, but a lot better than the float solution.
The most significant digit is in digits[0].
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Sat Jun 19, 2010 1:56 am |
|
|
I have made the following changes
Code: |
int16 int_total_rs;
int_total_rs = (int16) total_rs;
hunds =(int8) (total_rs/100);
tens =(int8) ((int_total_rs/10)%10);
ones =(int8) ((int_total_rs % 10)) ;
tenth =(int8) (((int_total_rs*10)%100)%10);
hundredth=(int8) (((int_total_rs*100)%100)%10);
|
code is compiling without any error.
But i am not getting the values of tenth and hundredth,all other values i am getting (hunds,tens,ones). |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Sat Jun 19, 2010 3:05 am |
|
|
Of course you are not....
What type of number can an integer hold?.
Why do you think I multiply the float value by 100, before using it as an integer in my version?.
Worth understanding that '%', performs a division, and gives the remainder. '/' performs a division. The ldiv operator, performs a single divsion, and gives you the result, _and_ the remainder in one operation. Half the time.
As posted, you perform 8 integer divsions, and two multiplications. About 3300 machine cycles. Using lfiv, reduces this to about 1/3rd the cycles...
The equivalent using your target names, is:
Code: |
ldiv_t ldivval;
float starting_val;
ldivval=ldiv((signed int16)(starting_val*100),10);
hundredth=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
tenth=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
ones=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
tens=ldivval.rem;
hunds=ldivval.quot;
|
Be aware at this point, of the limitations of signed and unsigned 16bit integers on 'size'. This version will fail if the value is above 327.67, while the version using unsigned intgers and not using ldiv, will fail above 655.35. You need to consider how youare going to handle the situation when numbers are above the limits.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Sat Jun 19, 2010 5:49 am |
|
|
Thanks Ttelmah for your option.
Kindly guide me about the working of the given code so that i understand it and implement it easily.
Also will i require to include any driver file for that code. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Sat Jun 19, 2010 7:40 am |
|
|
'Driver', no. Read the compiler manual...
The 'point' is that ldiv, is a supplied function (you have to include stdlib.h, but the manual tells you this), which returns both the quotient, and remainder from an integer division.
So you start with a float number. Say 145.6723.
Then you multiply this by ten, and convert this to an integer, so you have now got '14567'. You have 'lost' the 23 (this is what was happening to your code, but without the multiplication, you would lose the '.6723'.
Divide this by ten, and you now have 1456, with the _remainder_ 7. The bottom digit wanted.
Do it again. 145, remainder 6.
and again.
14, remainder 5.
and again.
1, remainder 4.
The '1' left as the quotient after the last division is the top digit.
So you get the digits in reverse order.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Sat Jun 19, 2010 7:58 am |
|
|
Hm,that's exactly what i want.
I have included the stdlib.h
but it is giving alot of errors
first error : ldiv_t ldivval;//what should i declear here.
i am using " total_rs " instead of " starting_val "
2nd error : " .rem"
3rd error : " quot "
how to resolve these errors. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Sat Jun 19, 2010 8:30 am |
|
|
Code: |
#include <18F2321.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=10000000)
#include <stdlib.h>
int8 hundredth,tenth,ones,tens,hunds;
void main(void){
ldiv_t ldivval;
float total_rsl=234.21;
ldivval=ldiv((signed int16)(total_rs*100),10);
hundredth=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
tenth=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
ones=ldivval.rem;
ldivval=ldiv(ldivval.quot,10);
tens=ldivval.rem;
hunds=ldivval.quot;
while(1);
}
|
A 'minimum' program showing how to declare things. stdlib.h, includes the definition of 'ldiv_t'. What you are seeing, is that this is not defined. Something is wrong with your including of this file, or you are trying to declare the variable in the wrong place (remember all variable declarations have to be at the start of a code block), or you have a _very_ old compiler (ldiv, didn't exist about 10 years ago....).
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Sun Jun 20, 2010 11:54 pm |
|
|
Ttelmah the routine is working fine but as you mentioned that
Quote: | This version will fail if the value is above 327.67 |
Is there any solution for this.
I will also use thousand's portion which is not in the current theme.
so after changing my current theme it will looks like
thousand,hundred,tens,ones,tenth,hunderedth.
And i think it is not possible using the current function for the thousand value bcoz the limit of the value is 327.67 |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 21, 2010 12:04 pm |
|
|
You could use sprintf to put formatted ascii numbers in a buffer.
I assume that your number will never be greater than 999.99.
By using the format "%6.2f", if the number has only 1 or 2 digits
on the left side of the decimal, then leading spaces will be added
to the output by the compiler. This allows you to know the position
of each digit in the buffer. You can then get each digit from the
buffer with a line of code. The digit is in ASCII format. You never
told us why you want to do this. Maybe ASCII is the format that
you want. If not, you can convert the digit to binary.
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//==========================================
void main()
{
int8 buffer[20];
float value;
value = 987.65;
sprintf(buffer, "%6.2f", value);
puts(buffer);
value = 87.6;
sprintf(buffer, "%6.2f", value);
puts(buffer);
value = 7;
sprintf(buffer, "%6.2f", value);
puts(buffer);
while(1);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|