|
|
View previous topic :: View next topic |
Author |
Message |
z1rqdym
Joined: 14 Dec 2014 Posts: 24
|
variables and their calculations on CCS C |
Posted: Wed Aug 12, 2015 6:33 am |
|
|
compiler version 5.015
mcu/dsp : dsPIC33F
i want to know something about variables and calculations.
example:
Code: |
float k;
int16 x, y, z;
x=12546;
y=15098;
z=x+y;
k=(float)z/2;
z=(int16)k; |
So what changes when we use (float) and (int16) before the variables?
Is it not the same as;
this?
Whats the difference?
My second question is about double variables. I know that CCS C don't support it. But its support float64 vatiable type.
Whats the difference between float64 and double variables on CCS C ? |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
Re: variables and their calculations on CCS C |
Posted: Wed Aug 12, 2015 7:29 am |
|
|
z1rqdym wrote: |
example:
Code: |
float k;
int16 x, y, z;
x=12546;
y=15098;
z=x+y;
k=(float)z/2;
z=(int16)k; |
So what changes when we use (float) and (int16) before the variables?
Is it not the same as;
this?
|
Your code should give the same answers, but that is to do with the values you chose for your example - your values are all even.
Let's consider a simplified version of your example:
Code: |
float k;
int16 x, y, z;
x=1;
y=2;
z=x+y;
k=(float)z/2;
z=(int16)k; |
Now k will be 1.5 (probably precisely, and not, say, 1.4999998) as 1.5 can be represented accurately by floating point). z will be 1.
(float) and (int) are called "casts" and they tell the compiler to convert, as best it can, the value in the variable into the request type. So, (float)k says "take the value of k and convert it to a float, then use that float value in the rest of the expression". Z at that point is 3, and it gets converted, precisely, to 3.0f ('f/ meaning float). Then it gets divided by 2, or in fact, the 2 also gets treated as a float as z is now a float, so the value used in the calculation is actually 2.0f, giving a result of 1.5f, which is stored in the float k. Note had z been even, then it could have been divided by two to give an integer result. We need it to be odd for this example to show what's happening.
z = (int16)k says convert k to an int16 then store the result in z. but 1.5f cannot be represented by an integer, so it gets truncated (NOT rounded) to 1, and so z ends up with 1 in it.
When you do k=z/2; z is treated as an integer and 3/2 = 1 in integer arithmatic. It is then converted to a float and stored in k, so k ends up as 1.0f. When z=k; is executed, the value of k, 1.0f, is converted to an integer, i.e. 1, and stored in z, which gets to be 1 just as before. So in these two cases z is the same, but k is different.
Quote: |
My second question is about double variables. I know that CCS C don't support it. But its support float64 vatiable type.
Whats the difference between float64 and double variables on CCS C?
|
Double variables are generally the same as float64s. Float32 is sometimes called single, or just float. CCS C does not support doubles on 10, 12, 16 and 18 series PICs, i.e. PCH and PCW compilers. All floats and doubles are float32s, or floats. On these ints are unsigned int8s by default.
24, dsPics, dspic33s, i.e. the PCD compiler, support doubles/float64s as well as floats/float32s while integers are signed int16s by default. CCS C on your dsPIC33F therefore DOES support doubles. Beware, as which
help file you see when you ask for help in the IDE is not obvious and depends on how the IDe is started up. This means it might be that the help is telling you it can't support doubles when actually it can with your device. I confess I don't know how to make sure you're seeing the right help.
Floats/float32s, at least on PCH and PCW compilers, are not IEEE754 compatible. They nearly are, but the format is re-arranged. There are conversions routines to convert from CCS to IEEE754 format shoud it be necessary. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19550
|
|
Posted: Wed Aug 12, 2015 8:34 am |
|
|
The key point though is the maths type.
This is fundamental to C (not just CCS C).
In C, if you perform arithmetic between two values. Say int16/int8, then int16 arithmetic will be used. C 'looks' at the types of the two variables, and uses the type of the 'highest' variable.
Types are organised as:
double (PCD only)
float
signed int32
int32
signed int16
int16
signed int8
int8
(highest to lowest)
Now types carry forward. So:
(int16*int8) / int8
Will use int16 arithmetic everywhere - the first expression has an int16, so the int8 is converted to int16, and int16 arithmetic used. The result is then int16, so the next sum becomes int16/int8, and int16 arithmetic will be used.
Important thing is that it is the types of the two arguments, _not_ the final result.
So if you have a sum like:
float = int16/int8
int16 arithmetic is used.
So if you did y/k (int16), 15098/12546, and put the result into a float, the result would be 1. Int's don't have a fractional part.
This becomes particularly important on CCS C, because unlike a lot of PC "C's", the maths is all library based. Historically this was the case on early computers and so the PDP-8, used 12bit arithmetic, and this was the default size of it's 'integer'. However on things like the PC (except for the earliest models), we get spoilt, and maths is now done by the CPU itself, but the FPU. A separate part just optimised to do arithmetic. This has the design that it'll automatically 'overflow' if needed. So if you do int16*int16, you can get an int32 result. This 'hides' the way that C historically (and on the PIC) handles maths. CCS C also defaults to int8, as the default integer size, so problems can appear earlier than on systems where int16 is the default.
The advantage of the constrained math type, for a device without the FPU, is speed, and size. An int8 division takes 11.3uSec on a modern PIC18. Int16, 32uSec, int32 106.6uSec, and float 144.9. Because you know what maths type is involved, the speed is known and won't change. However values can (and will) overflow with data lost. The maths code for larger types also grows enormously, so if you tried to use a automatic switching library on a PIC16, it probably wouldn't even fit.
The 'cast' allows you to convert a value _before_ the maths is performed. So:
So if you do (float)y/k, the result is the float 1.203411.
You need to consider what maths type to use, where you can save space and time by using smaller types, and ensure that your values are inside the ranges that can be handled by the maths as you write your code.
Also don't get 'fooled' by the apparent abilities of floating point. A 32bit FP value, offers _less_ precision than an int32. Only 23bits of actual 'precision' (technically 23.5 bits), what you gain is the ability to handle numbers over a massive range. What you lose is accuracy. Try doing some financial calculations using float, and then be surprised at how many digits 'out' your final result will be. Financial calculations are normally done using 'scaled integers', so counting 'integer cents' for example, to avoid this....
Most jobs on the PIC involve numbers with a constrained 'range' (ADC values for example), so it is worth not using unnecessarily complex maths types for dealing with this. |
|
|
|
|
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
|