I haven't done a lot of floating point math programming in any language let alone in C.
I'm writing a temperature conversion program as an exercise and have a question about floating point numbers. I have a code frag as listed below. In both cases Temp1 and Temp2 are 0.0 when P_FahrenheitTemp is <> 32.0. However, if I use the CF3 factor in the calculation the LOC VERRKKKS!!! :-)
This seems intuitively obvious to me but... Is this compiler dependent or is a cast operator necessary on the initialization? BTW, I'm writing this code on an IBM iSeries platform using the C/C compiler which strictly adheres to ASNI and ISO standards.
Thank you in advance for any info!
Martin Kuester
#define CF3 5/9;
float Conv2Celsius(float P_FahrenheitTemp)
{
float Temp1, Temp2, Temp3;
float ConvAdj = 32.0;
float CF1 = 0.555556;
float CF2 = 5/9;
//[°C] = ([°F] - 32) × 5/9
Temp1 = (P_FahrenheitTemp - ConvAdj) * CF1;
Temp2 = (P_FahrenheitTemp - ConvAdj) * CF2;
Temp3 = (P_FahrenheitTemp - ConvAdj) * CF3;
return(Temperature);
}
CodePudding user response:
Let us look closer.
float CF1 = 0.555556;
Temp1 = (P_FahrenheitTemp - ConvAdj) * CF1;
// same as
Temp1 = (P_FahrenheitTemp - ConvAdj) * (float) 0.555556;
float CF2 = 5/9;
Temp2 = (P_FahrenheitTemp - ConvAdj) * CF2;
// same as
float CF2 = 0; // 5/9 is integer division
Temp2 = (P_FahrenheitTemp - ConvAdj) * 0;
#define CF3 5/9
Temp3 = (P_FahrenheitTemp - ConvAdj) * CF3;
// same as
Temp3 = (P_FahrenheitTemp - ConvAdj) * 5 / 9;
Temp3 = (P_FahrenheitTemp - ConvAdj) * 5.0f / 9;
// ^--- float multiplication -------^
// same as
Temp3 = (P_FahrenheitTemp - ConvAdj) * 5.0f / 9.0f;
// ^--- float divsion ----------------------^
Temp3
"VERRKKKS" because it is not scaling by 5/9
. Instead it is a text substitution in the line-of-code and so multiplies by 5 and then divides by 9.
Temp3
is correct and best of the three.
Temp1
is almost correct as not as certainly precise * (float) 0.555556
as * 5.0f/9.0f
.
Temp2
is wrong as the answer is always 0, even when it should not be
I have a code frag as listed below. In both cases Temp1 and Temp2 are 0.0 when P_FahrenheitTemp is <> 32.0.
Temp1
is not 0.0.
To set aside the minor additional error in the constant, use at least 9 digits with float
and a f
suffix.
//float CF1 = 0.555556;
float CF1 = 0.555555556f;
Suggested replacement
float Conv2Celsius(float P_FahrenheitTemp) {
float ConvAdj = 32.0f;
float CF = 5.0f/9.0f; // or 0.555555556f
//[°C] = ([°F] - 32) × 5/9
return (P_FahrenheitTemp - ConvAdj) * CF;
}
CodePudding user response:
In C language the line float CF2 = 5/9;
will be processed as follows:
- The right side of the assignment operator
5/9
is evaluated first. The compiler here sees two integer values divided on each other so it will save the result into an integer temporary variable. This will lead to truncation of the fractional part of the actual result0.555556
to0
. - The result will be assigned then to CF2.
What to do?
Alot of options; float CF2 = 5.0/9;
or float CF2 = (float)5/9;
or even float CF2 = 5./9;
the same with CF3