-1

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;  
        }

}
Andre
  • 51
  • 9
  • 2
    why negating my question ? I have provided an example with snipped code – Andre Sep 27 '16 at 11:27
  • 2
    Your "test case" contains some function calls to some unknown function using arguments that we have no idea about. It's like asking: Why doesn't this code work: `x = foo(bar)`? – Art Sep 27 '16 at 11:37
  • **Always** prefer `double` when dealing with floating point numbers -- **never** `float` (and very very seldom `long double`). – pmg Sep 27 '16 at 11:37
  • @pmg I don't have a function that converts a fract32 to double – Andre Sep 27 '16 at 11:40
  • 2
    @pmg Context matters. Some would say the exact opposite. – 2501 Sep 27 '16 at 11:41
  • 2
    Considering the previous questions you posted the last days, it looks as if this project is too challenging for your current knowledge. Instead of using us to do your job, why not get the fundamentals yourself first? Re the code: if you permanently convert float to frac and back, it would be easier and like faster to use float throughout your code. The reason to use fractional is typically **to avoid** using float. – too honest for this site Sep 27 '16 at 11:45
  • 1
    @pmg: Depending on the necessary precision, `float` is sufficient. Especially on embedded systems (these often use the same representation for both types). – too honest for this site Sep 27 '16 at 11:46
  • @Olaf The problem that I have the data as fractional and I want to compare, multiply them by constants, how would I multiply a fract32 with 1.2, and the fract32 range is -1,1. That's the problem – Andre Sep 27 '16 at 11:46
  • @Andre: That's what mean with "you have to learn". No offence, but asking about **particular** problems in a very specific way will result in catastrophic results (from a performance and maintenance view). How about first learning about fractional arithmetic? There are very well ways to multiply a frac with an integer. For instance: `1.2 = (1 + 0.2)`. – too honest for this site Sep 27 '16 at 11:49
  • @Olaf so to multiply for example 0.8 by a fraction like that fr32_to_float(GO_coil_H[0].re)*0.8f. I would do mult_fr1x32x32( GO_coil_H[0].re, 0.2f) – Andre Sep 27 '16 at 12:10
  • You need to go review the c operators and their precedence. Do you understand the difference between the `&` and `&&` operators? Do you know whether `<` takes precedence over `?`. And is `? 1 : 0` really necessary? – kkrambo Sep 27 '16 at 14:16
  • @Olaf Thanks . I used your method ( 1 + 0.2) which is value + 0.2*value – Andre Sep 27 '16 at 17:07

2 Answers2

1

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.0f - 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);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • @did you forget to put 1.0f instead of 1.0d ? – Andre Sep 27 '16 at 17:05
  • would you comment it a little bit, I still didn't get the logic. so you get the upper limit and the lower limit of the factor, and then what do you do ? – Andre Sep 27 '16 at 18:08
  • @Andre `limitp` and `limitm` are not the upper limit and the lower limit. `limitm` is the smaller in magnitude limit (closer to 0.0) and `limitp` is the greater in magnitude one. If `x>limitm`, then `x <= limitp` is 1 or 0 corresponding to if `x` is between `limitp` and `limitm` or not. If `x= limitp` . – chux - Reinstate Monica Sep 27 '16 at 18:42
  • It is completely nonsense to convert back and forth between `float` and fraction. I wounder why OP uses a Fixed-point DSP if he uses (software) float anyway. An ARM Cortex-M4F would be faster. – too honest for this site Sep 27 '16 at 23:47
0

If you want to compare fractions - do not use floating-point at all. Convert them to the same denominator and compare numerators.

Sergio
  • 8,099
  • 2
  • 26
  • 52
  • can you provide an example ? I didn't get how to convert them to the same denominator ? – Andre Sep 27 '16 at 11:30
  • easiest would be to multiply fraction a with the denominator of b and vice-versa. This gives common denominators. You can then compare the numerators. – merl Sep 27 '16 at 11:32
  • @Andre [This](https://en.wikipedia.org/wiki/Fraction_(mathematics)#Comparing_fractions) should be helpful. – Sergio Sep 27 '16 at 11:33
  • @merl the fract32 range is -1,1. If I want to multiply fract32 A * 1.2, I would write A*10. Then compare A with 12 ? correct ? but A*10 would overflow the fract32 – Andre Sep 27 '16 at 11:35
  • @Andre I am not familiar with your data types, this is just the concept. You should read the wiki page about comparing fractions which Serhio linked. If you don't find a better may to compare the fractions you might need to change your data type or use another temporary data type for comparison. – merl Sep 27 '16 at 11:39
  • @merl how would I convert that sentence to common denominator fr32_to_float(GO_coil_H[0].im)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.imFundamental) – Andre Sep 27 '16 at 11:41
  • a * 0.8f < b should be equal to ((a * 4) / 5) < b so you can compare 4 * a < 5 * b – merl Sep 27 '16 at 12:22