-1

I am trying to create a conversion table using the C programing language. I want to convert the temperature from -250 °F to 250 °C increments of 10. However, I am not getting the Celsius output:

#include <p18f458.h>
#include <stdio.h>

#pragma config WDT = OFF

#define LOWER -250 /* lower limit of table */
#define UPPER 250 /* upper limit */
#define STEP 10 /* step size */

void main(void)
{
    int fh, cel;
    cel = (fh - 32) * 5 / 9;

    for (fh = LOWER; fh <= UPPER; fh = fh + STEP)
        printf("%d \t   %6.1f\n", fh, cel);

    while(1);  
} 
 Fahrenheit      Celsius

-250       
-240       
-230       
-220       
-210       
-200       
-190       
-180       
-170       
-160       
-150       
-140       
-130       
-120       
-110 .......

The code runs on a PIC18F458 microcontroller.

5
  • 3
    Well, for one thing cel is not an f. Commented Sep 26, 2022 at 18:06
  • 1
    You need to use floating point. Declare fh and cel as type double. Commented Sep 26, 2022 at 18:10
  • 5
    You'll need to recalulate cel in each loop iteration. Your cel = (fh - 32) * 5 / 9; does not establish a relationship but is a one-off calculation (from an uninitialised fh). Commented Sep 26, 2022 at 18:12
  • 1
    This exact question has been asked many times before. However, in your specific case the solution is not to use floating point since you don't have a FPU. Floating point will mean massive overhead bloat in the form of software libs inlined with the code. Instead simply multiply the left operand sufficiently before division, until you get the precision required. Commented Sep 27, 2022 at 6:53
  • Adding FP support to an embedded processor certainly is sizeable, yet the size needed - which tends to be fixed - is less and less of a concern each year as sizeable processors continue to increase dramatically. It use to be a significant concern with a 4k-byte processor, but with a 256k, less so. A key trade off is the cost of N * larger/more expensive processors vs the higher skill/cost of the programmer needed to handle FP-less applications. Commented Sep 27, 2022 at 13:58

3 Answers 3

1

Recalculate each time

Use floating point math


//     dddd123456789012ffffff
puts(" Fahrenheit      Celsius");

// cel = (fh - 32) * 5 / 9;

for (fh = LOWER; fh <= UPPER; fh = fh + STEP) {
  double cel = (fh - 32.0) * 5.0 / 9.0;
  printf(" %4d            %6.1f\n", fh, cel);
}

If wanting to avoid floating point types and math, use a scaled integer math to calculate decidegrees to achieve "%6.1f" like output. Scale temperature by 10. Integer division truncates the fraction, so add a signed offset of 5 to form a rounded result.

  int offset = (fh - 32) > 0 : 5  : -5;
  int deci_celcuis = ((fh - 32) * 10 * 5 + offset) / 9;

Printing is a little tricky. Various approaches exist.

  int whole = deci_celcuis/10;
  int frac = deci_celcuis%10;
  char *sign = (whole < 0 || frac < 0) ? "-", ""; 
  printf(" %4d            %s%d.%d\n", fh, sign, abs(whole), abs(frac));
Sign up to request clarification or add additional context in comments.

7 Comments

Note the embedded tag, this is a PIC. The OP doesn't have a FPU so this is bad advise. The equation has to be carried out in fixed point, for example by multiplying the left operand by 10000 or so before division.
@Lundin, Fixed point is a reasonable and not-so-difficult to do when FP math is expensive. Trivial with unsigned math, a tad more complex with signed math. Answer updated to support that. Converting signed fixed point though to text is a bit of a pain. A more expansive answer would use a generalized helper function. Above uses crafted code to get the job done.
I strongly suspect that this is an "XY" question anyway. A temperature sensor in an embedded system will not typically give output in degrees, but in a raw value between 0V and Vref. That's how simple, single-chip temp sensors work anyway. In which cases it is senseless for the MCU to use any other unit than "raw binary" from 0 to for example a max ADC ref value. You'd only convert to Fahrenheit or Celsius if you need to actually display something to humans.
Duplicate answer at another SE site: electronics.stackexchange.com/a/494924/6102
@Lundin True, yet many embedded processors drive small displays, so text output not that uncommon. Also with IOT, converting to a transmittable standard form often involves common SI units.
|
0

As others have noted: 1) use floating point to avoid integer division and truncation errors, 2) recalculate values inside the loop.

It would be a shame to miss this opportunity to produce parallel tables of F->C and also C->F for the given range.

#define LOWER  -250
#define UPPER   250
#define STEP     10

int main() {
    puts( "    F        C             C        F" );

    for( int i = UPPER; i >= LOWER; i -= STEP ) {
        printf( "%6.0f   %6.0f", (double)i, (i - 32.0) * 5.0 / 9.0 );
        printf( "        " );
        printf( "%6.0f   %6.0f\n", (double)i, i * 9.0 / 5.0 + 32.0 );
    }

    return 0;
}
    F        C             C        F
   250      121           250      482
   240      116           240      464
   230      110           230      446
   220      104           220      428
   210       99           210      410
   200       93           200      392
// omitted...
  -220     -140          -220     -364
  -230     -146          -230     -382
  -240     -151          -240     -400
  -250     -157          -250     -418

Ordinary mercury thermometers condition people to expect warmer temperatures at the top, and cooler temperatures 'below'... This table reverses the sequence presented in the OP to conform to people's expectations.

Comments

-2
cel = (fh - 32) * 5 / 9;

This statement is outside the loop, hence it will only ever print once. . Add it in the loop and your code would work as expected.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.