I'm having some problems and getting confused about the proper way of doing some operations with uint16_t and double for C embedded software (Using GCC).
Ex1:
uint16_t PD_input =723;// Input will always be greater than output
uint16_t PD_output =246;
uint16_t FQ_u16 = PD_input/PD_output;
This will result in: FQ_u16=2, no?
Ex2:
uint16_t PD_input =723;
uint16_t PD_output =246;
double FQ_dbl = PD_input/PD_output;
In this case FQ_dbl =2.9390, but I get 0.... or should I do:
double FQ_dbl = (double)(PD_input/PD_output);
In this case I don't know if doinng the casting will cause some problems. I get 0 anyway.
If I do the casting on the other side the next example will be correct, or how should I do it? Ex3:
double FQ_dbl = PD_input/PD_output;
uint16_t var= (uint16_t)FQ_dbl; //Is this correct?
What is the proper way of dividing two uint16_t? What is the proper way of casting/convert a double to an uint16_t?
Ex4:
uint16_t var=7342;
double target = var/1000;
target=7.342?-->I get 0
EDIT: I try this example using UNITY (It uses GCC)
uint16_t Operations(void)
{
uint16_t PD_input=723;
uint16_t PD_output=246;
uint16_t FQ_u16_raw=PD_input/PD_output;
uint16_t FQ_u16 = (PD_input + (PD_output >> 1)) / PD_output;
printf("FQ_u16: %d, FQ_u16_raw: %d",FQ_u16,FQ_u16_raw);
double FQ_dbl=(PD_input/PD_output);
printf("\nFQ_dbl: %d, FQ_dbl:%f",FQ_dbl,FQ_dbl);
FQ_dbl=(double)(PD_input/PD_output);
printf("\nFQ_dbl: %d, FQ_dbl:%f",FQ_dbl,FQ_dbl);
FQ_dbl=((double)PD_input)/PD_output;
printf("\nFQ_dbl: %d, FQ_dbl:%f",FQ_dbl,FQ_dbl);
printf("\n********************");
uint16_t target=7341;
double target_dbl=target/1000;
printf("\ntarget_dbl: %d,target_dbl:%f",target_dbl,target_dbl);
return FQ_u16;
}
I get this as output:
- "FQ_u16: 3, FQ_u16_raw: 2"
- "FQ_dbl: 0, FQ_dbl:0.000000"
- "FQ_dbl: 0, FQ_dbl:0.000000"
- "FQ_dbl: 942797699, FQ_dbl:0.000000"
- "********************"
- "target_dbl: 0,target_dbl:0.000000"
For a divide operation to be promoted to
doubleat least one of teh operatnds must bedouble. To that end you need to cast one or both operands, not the expression after the divide operation. So in:PD_input/PD_outputis an integer divide which you then explicitly cast todouble(though it would implicitly converted in any case).What you need in this case is:
Casting
PD_inputto double implicitly promotesPD_outputtodoubleand provided a floating point divide.You could equally be explicit throughout:
but it is equivalent.
For expressions involving literal constants such as:
it is sufficient to use a
doubleliteral as follows:but again:
is the explicit equivalent.
As an aside, you are consistently using the wrong formatter (
%d) for outputting adouble. You need%f. Include-Wformat(GCC) in your compile options to catch such errors (I think-Wformatis implicit inWallthat you should use in any case together with-Werror- do not ignore the warnings, they are often indicative of semantic errors as opposed to syntactic errors).