This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Float - uint comparison sometimes succeeding?

Hello Community! First time poster here :)

I am debugging some code and am completely perplexed by a comparison between and integer and a float that sometimes evaluates true.

In the following code, a floating-point calculation is performed, typecast to a unsigned integer, which is then compared to another float. I expect that in all but the zero case, this evaluation would fail. And usually it does. But sometimes it evaluates true, and I am trying to understand what conditions lead to this.

float gA = 0.00356270161773046;

float gB = 0.00336178532868241;

[...]

float sA = 0.5 / gA;

float sB = 0.5 / gB;

[...]

const float PA = sA * gA;

if(sB == (uint16_t)(PA / gB))
    // Evaluates true.

In the above code, gA and gB are similar but different values, set elsewhere in the snipped portion, and by varying them slightly I can change the result of the evaluation. For example:

if gB = 0.00336178532868241 -> TRUE

if gB = 0.00332519446796205 -> FALSE

But I don't understand why it is ever evaluating true..!

This code was written by someone else - who is much more experienced than me - and I have little idea what they are trying to achieve through this typecast to uint16_t. Can anyone recognise what is being done here? Does this cast operation have the same (converting/rounding) function as it does in gcc etc, or is it a true typecast?

This code is compiled via C51 for a C8051 microcontroller application, in case that is relevant. I cannot debug or rebuild the code.

Thank you!

Parents
  • Interesting. The cast to uint16_t should round positive numbers toward zero; negative values will become zero. I would guess that the original author was looking for cases where sB and (uint16_t)(PA/gB) had the same number of significant bits, but didn't want to use floor().

Reply
  • Interesting. The cast to uint16_t should round positive numbers toward zero; negative values will become zero. I would guess that the original author was looking for cases where sB and (uint16_t)(PA/gB) had the same number of significant bits, but didn't want to use floor().

Children
  • negative values will become zero.

    Only if they're larger than -1.0  All other cases cause undefined behavioiur.  As in: boom, your code just exploded.

    looking for cases where sB and (uint16_t)(PA/gB) had the same number of significant bits

    That doesn't even come close to what that code actually does, so let's hope that wasn't what it was meant to do.

  • Thanks for the thought - yes, that was my first interpretation too. If the author had cast both to uint16_t first, then it would be clear enough - if perhaps a little hacky. Indeed, I believe from the larger code operation that this to be the author's functional intention; to check if the s* values are nearly the same, and I would not expect any negative values in this context. I haven't ruled out that this is actually just an error that wasn't caught along the way; the author is pretty good, though, so I always assume they get it right and I just am mis-understanding (until proven otherwise :p)

  • Broeker, you are being quite aggressive with your response here. Adam is trying to help us understand what this code is doing by proposing a explanation, not saying how it should be done in an ideal, generalised way. I think you also full well know what Adam was trying to say in his explanation.