Thale
Thale

Reputation: 123

Embedded-C:How to perform division between 2 unsigned integers and display the answer in decimal format

I am new to embedded System. I would like to perform division between 2 unsigned 16 bit integer and display the answer(including the decimal values). I wonder how can I accomplish this in embedded-C. Float,double and unsigned long does not seem to work. I am using TI's TM4C launchpad.

uint8_t PPGMsg[5];
unsigned long PPG;
uint16_t IR_combined,RED_combined;
IR_combined = (PPGMsg[1]<< 8)|PPGMsg[2];
RED_combined = (PPGMsg[3]<< 8)|PPGMsg[4];
PPGMsg[0]=(RED_combined/IR_combined);
PPG=(RED_combined/IR_combined);
UARTprintf("IR_combined is: %d\n",IR_combined);
UARTprintf("RED_combined is: %d\n",RED_combined);
UARTprintf("PPG is: %d\n",PPGMsg[0]);
UARTprintf("long PPG is: %d\n",PPG);

For example when IR_combined is: 147 and RED_combined is: 1012, the PPG: 6. However I would like the answer to be displayed as 6.88 instead.

Upvotes: 0

Views: 1665

Answers (1)

Lundin
Lundin

Reputation: 214920

For 2 decimals precision, you need to do (uint32_t)RED_combined*100/IR_combined. Then print the decimals as you would like them. Example:

#include <stdint.h>
#include <inttypes.h>
...
uint16_t RED_combined = 1012;
uint16_t IR_combined = 147; 
uint16_t x = ((uint32_t)RED_combined*100u / IR_combined);
printf("%"PRIu16".%.2"PRIu16, x/100, x%100);

However, you also have lots of other problems/bugs:

  • IR_combined = (PPGMsg[1]<< 8)|PPGMsg[2]; is dangerous/buggy code. Since PPGMsg[1] is a small integer type, it gets promoted to int and you end up performing left shifts on a signed type. Similarly, the | invokes implicit promotion to signed type.
    You must study Implicit type promotion rules.
  • (PPGMsg[3]<< 8)|PPGMsg[4]; Same bugs here.
  • PPGMsg[0]=(RED_combined/IR_combined); You store the result in a 8 bit variable that is too small to hold the result. I don't understand how this makes any sense. Are you trying to parse out the ls byte?
  • %d is used to print signed integers. UARTprintf("IR_combined is: %d\n",IR_combined); should be "IR_combined is: %"PRIu16 "\n",IR_combined. You find these format specifier macros in inttypes.h.
  • Same bug: UARTprintf("PPG is: %d\n",PPGMsg[0]);. Should be UARTprintf("PPG is: %"PRIu8 "\n",PPGMsg[0]);.
  • unsigned long is printed with %ld

Using the correct type matters, everywhere!

Also consider using a good compiler like gcc that does warn if you use the wrong format specifier. Or better yet, don't use printf-like functions at all - they are unsafe, slow and resource-heavy.

Upvotes: 2

Related Questions