Andre Andre - 2 months ago 17
C Question

Converting fractions to floating point

I'm trying to convert a fraction to floating point and use it for comparison.
but the values are too small and it returns true for the results of the Boolean variables. is my converision correct ? or should I do it in another way which I don't know ?

A test case:

// result is -0.0074
float coilh0re = fr32_to_float(GO_coil_H[0].re)*0.8f;
// result is -0.0092
float coilrefundamental = fr32_to_float(CoilEepromData.coilboardhspule.reFundamental);
// result is -0.01123
float coilh0re2 = fr32_to_float(GO_coil_H[0].re)*1.2f;
-0.0074>-0.0092> -0.01123


here is a snipped of the code

bool resultA = fr32_to_float(GO_coil_H[0].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reFundamental) ? 1 : 0;
bool resultB = fr32_to_float(CoilEepromData.coilboardhspule.reFundamental) <= fr32_to_float(GO_coil_H[0].re)*1.2f ? 1 : 0;

bool resultAB = !(resultA & resultB); // always true

bool resultC = fr32_to_float(GO_coil_H[1].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic) ? 1:0;
bool resultD = fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic) <= fr32_to_float(GO_coil_H[1].re)*1.2f ? 1:0;

bool resultCD = !(resultC & resultD); // always true

bool resultE = fr32_to_float(GO_coil_H[0].im)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.imFundamental)? 1 : 0;
bool resultF = fr32_to_float(CoilEepromData.coilboardhspule.imFundamental) <= fr32_to_float(GO_coil_H[0].im)*1.2f ? 1 : 0;

bool resultEF = !(resultE & resultF);// always true

bool resultG = fr32_to_float(GO_coil_H[1].im)*0.8f < CoilEepromData.coilboardhspule.imHarmonic ? 1 : 0;
bool resultH = fr32_to_float(CoilEepromData.coilboardhspule.imHarmonic) <= fr32_to_float(GO_coil_H[1].im)*1.2f ? 1 : 0;

bool resultGH = !(resultG & resultH);// always true

if(! ((fr32_to_float(GO_coil_H[0].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reFundamental)) && (fr32_to_float(CoilEepromData.coilboardhspule.reFundamental) <= fr32_to_float(GO_coil_H[0].re)*1.2f) )
|| ! ((fr32_to_float(GO_coil_H[1].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic)) && (fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic) <= fr32_to_float(GO_coil_H[1].re)*1.2f) )
|| ! ((fr32_to_float(GO_coil_H[0].im)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.imFundamental)) && (fr32_to_float(CoilEepromData.coilboardhspule.imFundamental) <= fr32_to_float(GO_coil_H[0].im)*1.2f) )
|| ! ((fr32_to_float(GO_coil_H[1].im)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.imHarmonic)) && (fr32_to_float(CoilEepromData.coilboardhspule.imHarmonic) <= fr32_to_float(GO_coil_H[1].im)*1.2f) ) )

{
eUserCode = E_USER_SOIL_FAILED;
eProcessState = E_ERROR_HANDLING;
}

}

Answer

If appears OP wants to test if a value reFundamental is in range +/-20% of re. This is not a float precision issue, but a math one.

// Simplified problem
float re = -0.01123f/1.2f;
float reFundamental = -0.0092f;
bool resultA  = re*0.8f < reFundamental;
bool resultB  = reFundamental <= re*1.2f;
bool resultAB = !(resultA & resultB); // always true

But the values are negative and so the < and <= should be reversed.

Various alternatives. Example: (Adjust to taste)

bool in_range(float x, float limit, float factor) {
  float limitp = limit*(1.0f + factor);
  float limitm = limit*(1.0d - factor);

  if (x > limitm) return x <= limitp;
  if (x < limitm) return x >= limitp;
  return x == limitp;
}

bool resultAB = !in_range(fr32_to_float(CoilEepromData.coilboardhspule.reFundamental),   
    fr32_to_float(GO_coil_H[0].re), 0.20);