|
|
View previous topic :: View next topic |
Author |
Message |
small_chick
Joined: 17 Jul 2012 Posts: 53
|
change type of variables ? |
Posted: Fri Dec 14, 2012 10:38 pm |
|
|
I'd like to do some calculation. Because I'd like to get more precise result so in the calculation transition, I use float variables but in the final result I want to change into sign int16 variables but there's a problem here!
Instead the right result is -450 but when I assign float variable value into signed int16 variable, I get 65085 ( = 2^16 -1 - 450). So how can I solve this problem ? ^~^ |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Dec 15, 2012 12:35 am |
|
|
I don't see any problem. When the following program is compiled with
vs. 4.140 and run in the MPLAB simulator, I get this output:
Test program:
Code: |
#include <18F4520.h>
#fuses INTRC_IO,NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
//=========================================
void main()
{
float value;
signed int16 result;
value = -450.0;
result = (signed int16)value;
printf("result = %ld", result);
while(1);
}
|
The problem is probably in your use of printf. Look at the format types
listed in the CCS manual, in the section on printf. You have to use the
correct printf format type specifier for the data type that you want to
display. You should memorize these format specifiers. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Dec 15, 2012 2:09 am |
|
|
and if you 'think about it a bit', a signed int16, can only hold +32767 to -32768. So if you are displaying 65085, you are not outputting it as 'signed'. However -450, in hex is FE3E. FE3E, displayed as an unsigned number, is 65086. So as PCM programmer says, you are outputting the value with the wrong printf format. However I also suspect you are not considering rounding/trimming. When a float is converted to an integer, it 'trims down'. No 4/5 rounding. So -449.99999, will give -449 when converted to an integer. So the number you are actually getting is -449, but you are then displaying this incorrectly.
To convert to integer with 4/5 rounding, needs something like:
Code: |
int16 round(float fval) {
if (fval>=0.0) return(fval+0.499999);
return (fval-0.499999);
}
|
It is worth understanding that C, is very much a 'loosely typed' language. Types don't actually get associated to the target routine. If a target routine expects an unsigned int16, and is 'handled' a signed int16, the byte values will be treated as unsigned. This is different from many latter languages, where if you do this, they will either throw an error, or will automatically convert.
Best Wishes |
|
|
small_chick
Joined: 17 Jul 2012 Posts: 53
|
|
Posted: Sat Dec 15, 2012 6:45 am |
|
|
Thanks Ttelmah & PCM ! I've solved my problem!
First, I code as follow:
Code: |
float64 measured_speed;
unsigned int16 temp;
measured_speed = (POSCNT - 32000)*1.875; /*POSCNT is an 16 bit register in dsPIC30F4011 of QEI module*/
if(measured_speed < 0)
temp = (unsigned int16)( - measured_speed);
else
temp = (unsigned int16)( measured_speed);
|
Then I get wrong result as I've mentioned above. After that, I changed
this line:
Code: | measured_speed = ((float64)POSCNT - 32000)*1.875; |
then it's well-done!
|
|
|
|
|
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
|