Question

I have the following piece of code (feel free to change the float with double):

class A
{
    public:
        void setValueFloat(float v) {
              m_floatValue = v / 3.6;  // m/s <-> km/h conversion
        }
        void setValueInt(int v1, int v2) { 
              m_intValue1 = v1; m_intValue2 = v2;
        }

        bool conditionIsOk()
        {
             if(m_intValue1 > m_intValue2)
             {
                  if(m_intValue1 - m_intValue2 > m_floatValue)
                  {
                      return true;
                  }
             }
             return false;
        }

    private:
        int m_intValue1, m_intValue2;
        float m_floatValue;

};

and somewhere else:

A a;
int something = 5; // Intentionally int
int somethingElse = 6; //these are just some numbers, not production data!!!
int moreStuff = 7;

a.setValueFloat(something);
a.setValueInt(somethingElse, moreStuff);
if(a.conditionIsOk())
{
   // Yippee!
}

And the questions:

  1. How safe is it to compare the result of an arithmetic operation on ints to a float given the situation above?

  2. Is it necessary to (float)m_intValue1 - (float)m_intValue2 > m_floatValue for this situation?

  3. Where in the C / C++ standard can I find a line about exactly this situation?

  4. What typecasts will be done by default for the simple situation m_intValue1 - m_intValue2 > m_floatValue ? (and how can I show this to someone else in a way that he also sees it (visually), "just believing that it works" is not enough :) )

Was it helpful?

Solution

  1. This depends on the actual implementation (i.e. which compiler and which architecture are used). On typical systems with 32 bit ints and IEEE754 binary32 floats integers can be represented exactly up to +-2^24 as floats, so not for the full range of possible values. So no, it is not safe in general, but may be safe if the used range of your integers (or in this case rather the difference!) and floats is limited appropriately.

  2. No! In fact m_intValue1 - m_intValue2 > m_floatValue is better as the conversion to float happens after the computation of the difference (see note about difference in the above point). You can be explicit and write static_cast<float>(m_intValue1 - m_intValue2) > m_floatValue, but this is not necessary.

  3. Conversions are covered in chapter 4 of the C++ standard (see draft N3242). In particular 4.9 Floating-integral conversions, also note 5§10 "usual arithmetic conversions" which also applies to comparisons. As the question is also tagged with C, in the C standard (see darft N1570) the corresponding section is 6.3.1 and in particular 6.3.1.4 and 6.3.1.8.

  4. See answers to 2. and 3.

OTHER TIPS

The usual rules on type promotion in binary operations apply. To quote the Standard (chapter 5. expressions)

9.Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result.

This pattern is called the usual arithmetic conversions, which are defined as follows:

If either operand is of scoped enumeration type (7.2), no conversions are performed;

if the other operand does not have the same type, the expression is ill-formed.

If either operand is of type long double, the other shall be converted to long double.

Otherwise, if either operand is double, the other shall be converted to double.

Otherwise, if either operand is float, the other shall be converted to float.

Otherwise, the integral promotions (4.5) shall be performed on both operands

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top