简体   繁体   中英

C (Embedded) - Divide uint16 and convert to double

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 double at least one of teh operatnds must be double . To that end you need to cast one or both operands, not the expression after the divide operation. So in:

double FQ_dbl = (double)(PD_input/PD_output);  

PD_input/PD_output is an integer divide which you then explicitly cast to double (though it would implicitly cast in any case).

What you need in this case is:

double FQ_dbl = (double)PD_input / PD_output ;  

Casting PD_input to double implicitly promotes PD_output to double and provided a floating point divide.

You could equally be explicit throughout:

double FQ_dbl = (double)PD_input / (double)PD_output ;  

but it is equivalent.

For expressions involving literal constants such as:

double target_dbl = target / 1000 ;

it is sufficient to use a double literal as follows:

double target_dbl = target / 1000.0 ;

but again:

double target_dbl = (double)target / 1000.0 ;

is the explicit equivalent.

As an aside, you are consistently using the wrong formatter ( %d ) for outputting a double . You need %f . Include -Wformat (GCC) in your compile options to catch such errors (I think -Wformat is implicit in Wall that 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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM