View previous topic :: View next topic |
Author |
Message |
Izzy
Joined: 27 May 2007 Posts: 106
|
How to take only 3 digits after float for calculation? |
Posted: Sun Apr 13, 2008 1:38 pm |
|
|
Say for eg. you have a value stored in a float variable.
Say I stored
float number = 2.456;
But it will stored
float number = 2.4562134654789; random bunch of numbers after the assigned valaue.
Now say I just want to use 2.456 from this above value for calculation, how do you do that?
I know you can do by multiplying by 1000 then converting to int....and so on..
But isn't there any other easy way?
Thanks in advance |
|
|
Ttelmah Guest
|
|
Posted: Sun Apr 13, 2008 2:54 pm |
|
|
Basically, no.
The float doesn't actually store 2.456. It stores a scaled binary representation of the value, and separately the scaling applied. Unfortunately, there is then no direct route from this value to a decimal 'number of digits'. You can as you say, multiply by 1000, and store as an integer. However remember that you should add 0.0004999 to the value (for +ve numbers) to get normal 4/5 rounding, or you will be always trimming 'downwards'.
Remember that you can use the %w printf formatter to output such scaled values directly, with the decimal point inserted, and that it is much faster if you can work with such values for the arithmetic itself.
For FP values there is normally not any reason to throw away accuracy. If you are going to do this, it should be the last thing done, or you increase the errors as arithmetic proceeds. For output, you always have the field width specifier, so the 'extra' characters need not be seen.
Best Wishes |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Apr 13, 2008 3:00 pm |
|
|
One more question:
When you print to a serial LCD, is there a way you can reserve space for ...say for eg 2.3 precision float? meaning 2 digit and 3 precision ...like 35.123
say if the print should start after 5th block on the 20 x 4 LCD.
_ _ _ _ _ 3 5 . 1 2 3
now I dont want the number to print
_ _ _ _ _ 2 . 2 2 3 if the number is 1 digit with 3 precision
I am trying to get something like
_ _ _ _ _ _ 2 . 2 2 3 ...Notice that the 6th block is empty, so that the decimal remains aligned.
Is it possible?
I tried using "%3.2f" but it only displays 2 digit with 3 precision , it does not leave the block empty if I am trying to print 1 float 3 precision float.
Does anyone knows about this? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 13, 2008 4:26 pm |
|
|
Do a test with an if() statement. If the number is less than 10.000
then print a space first. Then display the number. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Apr 13, 2008 4:36 pm |
|
|
Thanks for the reply.
If there were only couple of values to be displayed, I would have done that.
But I have almost 30 - 40 values to be displayed, so I am not sure if it would be appropiate. I will see. |
|
|
Ttelmah Guest
|
|
Posted: Mon Apr 14, 2008 2:59 am |
|
|
%3.2, shouldn't give '3 precision'. The number after the decimal, is the number of digits wanted after the decimal point (should be '3' for you), while the number in front, is the _total_ field width (must also include the decimal point, and the digits after the decimal). Normally, the specifier you would want, would be % 6.3f. Note the 'space'. However (unfortunately), CCS does not support this... :-(
However the number of things you have to output, doesn't mean you can't use a test. Also, you only seem to be talking about possible numbers up to 99.999 max (since this is the space you are allowing).
Generate your own output routine, like
Code: |
void right_just_val(float val) {
if (val >=10.) printf(lcd_putc"%6.3f",val);
else printf(lcd_putc" %5.3f",val);
}
|
This will handle positive numbers from 0.000 to 99.999. Simply position your write cursor on the LCD, where you want the number to print, and call this with the number (I am assuming you are using lcd_putc - otherwise substitute your own output function).
Best Wishes |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Mon Apr 14, 2008 12:01 pm |
|
|
Ttelmah is right in mentioning that there is nothing untoward occurring with
Quote: |
float number = 2.456;
But it will stored
float number = 2.4562134654789; random bunch of numbers after the assigned valaue. |
Perhaps the expectation of accuracy stems from a misconception as to what a number really is. We have inherited a notation over the last few thousand years. It has the form "2.456" using base ten and the 0...9 symbols. The PIC has registers that perform operations. If a binary notation of a number is transfered to a register then the PIC can manipulate it without translation. When "2.456" is typed while coding or read in through a port the ascii chars have to be translated. Float is stored as notation in the PIC data space and is manipulated via floating pt routines based on the base two ( binary) system. Moving between base ten to base two and back introduces notational differences. This is to be expected the value 1/3 can't be expressed fully in 1.nnnnn base ten notation and thats before base translation occurs. Handheld calculators avoid many of these issues by doing calculations in BCD and mimicking the long hand calculations we do with our inherited base ten notation.
Numbers calculated this way are often accepted as accurate and are used to question the accuracy of results from a binary based system. There is no real answer either we adopt binary notation or we design PIC like calculators. The calculator approach is not very efficient neither is changing to binary notation from decimal. That leaves us with the differences the two notations will from time to time introduce. |
|
|
Morcilla
Joined: 08 Apr 2008 Posts: 2
|
Recomend |
Posted: Thu May 22, 2008 7:58 am |
|
|
i recomend to use:
Code: |
sprintf(var,"%2.1f",pctrl->temp_set);
my_prints(1,1,var);
|
where my_prints function is
Code: |
void my_prints(unsigned char x ,unsigned char y ,char* s){
unsigned int len;
lcd_gotoxy(x,y);
len = strlen(s);
for(i=0;i<len;i++)
lcd_putc(s[i]);
}
|
this is more cheaper for the PIC than
Code: |
printf(lcd_putc"%2.1f",pctrl->temp_set);
|
Regards. |
|
|
|