stevepedwards.com/DebianAdmin linux mint IT admin tips info

Practical C Programming – Unitsconverter Prog: using fmod for float remainder

I wanted to extend the Imperial/metric converter further, by adding feet to the cm to inches conversion, so human heights could be displayed in a "6ft, 2in" style. It still needs the maths debugging for the whole 6 feet value remainder issue as shown:

 

I struggled with the logic and units for ages with this, as I knew I had to convert the fractional part of a foot to inches but did not know how to modify the modulus for integers (x%y) for float values to strip away the fraction then convert that back to imperial and "add it" back to the larger foot value as a rounded nearest inch.

I finally found an example explaining it needs the math.h lib - as other functions like power, square root, sin etc. do - and the simple format of remainder = fmod(dividend, divisor);

This resulted in the following extended code:

case '4':
printf("Want to convert (c) cm to inches/feet or (i) inches to cm?: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%c", &operator);
switch (operator)
{
case 'c':
printf("c: convert cm to inches. Enter cm value: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%f", &cm);
inches = cm * 0.393701;
feet = inches/12;
remaining = fmod(inches,12);
printf("%0.2f cm is %0.2f inches, or %0.0fft,%0.0lf ins! \n\n", cm,inches,feet,remaining);
break;
case 'i':
printf("i: convert inches to cm. Enter inches value: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%f", &inches);
cm = 1/0.393701*inches;
feet = inches/12;
remaining = fmod(inches,12);
printf("%0.0f \n", remaining);
printf("%0.1f inches is %0.1f cm or %0.0fft,%0.0lf ins! \n\n", inches,cm,feet,remaining);
}
break;
default:
{
printf("Invalid key, try again! %c\n\n", operator);

etc...

unitconvheight,png

To see how the maths works in the section:

printf("i: convert inches to cm. Enter inches value: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%f", &inches);
cm = 1/0.393701*inches;
feet = inches/12;
remaining = fmod(inches,12);
printf("%0.0f \n", remaining); /*temp test line to show the actual result of the fmod */
printf("%0.1f inches is %0.1f cm or %0.0fft,%0.0f ins! \n\n", inches,cm,feet,remaining);

The input is in inches in the first sub menu above, so that is converted to cm first as a fixed value.

The rounded nearest feet value is also converted as a fixed value.

To find the fractions of a foot, the fmod gives the excess ("float remaining;" declaration) as a decimal for inch values that are not exact multiples of 12. This remainder modulus of a foot is truncated or rounded to the nearest inch by allowing only a 0 decimal place float holder as %0.0f.

For example, 24 inches shows no "remaining" when fmod'd by 12, giving a 0 ins result, but 14 inches has a remainder 2.

The conversions are not exact but adequate, as 12.5 inches gets rounded down to 1ft, 0 in; and 12.6 inches gets rounded up to 1ft, 1 in. Ideal for this exercise.

I can now look at modifying the kg/pounds case for ounces in a similar way.

I tested the same values in reverse to check they were rounded closely enough to make sense below i.e. 33cm = 13ins = 12.99ins

This case 4 sub menu section now outputs:

./unitsconverter2
program to convert Imperial units to metric. Enter menu option:
1: km to miles
2: litres to pints
3: kg to pounds
4: cm to inches
q: quit
4
Want to convert (c) cm to inches/feet or (i) inches to cm?: i
i: convert inches to cm. Enter inches value: 13
1
13.0 inches is 33.0 cm or 1ft,1 ins!

program to convert Imperial units to metric. Enter menu option:
1: km to miles
2: litres to pints
3: kg to pounds
4: cm to inches
q: quit
4
Want to convert (c) cm to inches/feet or (i) inches to cm?: i
i: convert inches to cm. Enter inches value: 72
0
72.0 inches is 182.9 cm or 6ft,0 ins!

program to convert Imperial units to metric. Enter menu option:
1: km to miles
2: litres to pints
3: kg to pounds
4: cm to inches
q: quit
4
Want to convert (c) cm to inches/feet or (i) inches to cm?: i
i: convert inches to cm. Enter inches value: 65
5
65.0 inches is 165.1 cm or 5ft,5 ins!

program to convert Imperial units to metric. Enter menu option:
1: km to miles
2: litres to pints
3: kg to pounds
4: cm to inches
q: quit
4
Want to convert (c) cm to inches/feet or (i) inches to cm?: c
c: convert cm to inches. Enter cm value: 33
33.00 cm is 12.99 inches, or 1ft,1 ins!

program to convert Imperial units to metric. Enter menu option:
1: km to miles
2: litres to pints
3: kg to pounds
4: cm to inches
q: quit
4
Want to convert (c) cm to inches/feet or (i) inches to cm?: c
c: convert cm to inches. Enter cm value: 184
184.00 cm is 72.44 inches, or 6ft,0 ins!

program to convert Imperial units to metric. Enter menu option:
1: km to miles
2: litres to pints
3: kg to pounds
4: cm to inches
q: quit
w
Invalid key, try again! w

program to convert Imperial units to metric. Enter menu option:
1: km to miles
2: litres to pints
3: kg to pounds
4: cm to inches
q: quit
q

8/9/16 Just revisited this for revision and the answer to the incorrect 6ft problem is a simple rounding up issue solved by defining feet as an integer to round it down to correct feet; not a float! Duh...

case '4':
printf("Want to convert (c) cm to inches/feet or (i) inches to cm?: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%c", &operator);
switch (operator)
{
case 'c':
printf("c: convert cm to inches. Enter cm value: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%f", &cm);
inches = cm/2.54;
feet = inches/12;
remaining = fmod(inches,12);
printf("%0.1f cm is %0.1f inches, or %dft,%0.00f ins \n\n", cm,inches,feet,remaining);
break;
case 'i':
printf("i: convert inches to cm. Enter inches value: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%f", &inches);
cm = inches*2.54;
feet = inches/12;
remaining = fmod(inches,12);
printf("%0.0f \n", remaining);
printf("%0.1f inches is %0.1f cm or %dft,%0.00f ins \n\n", inches,cm,feet,remaining);
}
break;

The full version incl. ounces and yards is here:

unitsconverter2.c

Comments are closed.

Post Navigation