This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/TMS320F28379D: Preprocessor compare problem

Part Number: TMS320F28379D


Tool/software: TI C/C++ Compiler

Hello,

I have made in my code the following definition (TS_HS_SUB).

This definition is used in the code for a compare with a fixed time of 20 milliseconds.

“if (delay >= ((unsigned short)(20e-3/TS_HS_SUB)) )” should be fulfilled when delay is greater or equal to 20.

 

But this happens when delay is 19!

 

What is the reason for this problem?

 

Thank you very much

Ralf

  • Thank you for reporting this problem.  I can produce a similar result.  I filed the entry EXT_EP-10056 to have this investigated.  You are welcome to follow it with the link below in my signature.

    I'm less certain than usual that this is a bug in the compiler.  When it comes to evaluating floating point expressions, the smallest details matter.  I have been surprised before.  This may be one of those times.

    Thanks and regards,

    -George

  • It turns out that this is in fact a bug.  However, you should probably write the code a bit differently to avoid problems like this.

    Neither 20e-3 nor 1e-3 is exactly representable as a binary floating-point constant, so you should always suspect that arithmetic on such constants won't get you the algebraically precise value.  However, we can compute the precise expected value for floating-point division of these values.  The precise answer is a function of the number of precision bits in the float format and the rounding mode, which we'll assume is round-to-even.  It turns out that the answer (in binary) is 1.001111... times 2 to the power 4, which is ever-so-slightly less than 20.  This value should be rounded up to exactly 20, which is the nearest representable value.  The fact that it is not rounded up is a bug, which George has already recorded.

    To work around this problem, and to avoid problems like this with other float expressions, you should not cast from a floating-point type to an integer type without explicitly rounding.  Conversions to integer types truncate, so the value 19.9999 will get truncated to 19.0.

    To avoid this problem, you should do one of these things:

    • use (unsigned short)(20e-3/TS_HS_SUB+0.5)
    • use (unsigned short)lround(20e-3/TS_HS_SUB)
    • if you want exactly 20, use exactly 20: if (delay >= 20)
    • if you don't want to have the constant 20 as a magic number, define a new macro that represents the threshold, and place its definition next to that of TS_HS_SUB:
      • #define THRESHOLD 20 // (algebraic value of 20e-3/TS_HS_SUB)