Double divided by double and by integer: which one is better? - c++

I always assume that dividing a double by an integer will lead to faster code because the compiler will select the better microcode to compute:
double a;
double b = a/3.0;
double c = a/3; // will compute faster than b
For a single operation it does not matter, but for repetitive operations it can make difference. Is my assumption always correct or compiler or CPU dependent or whatever?
The same question applies for multiplication; i.e. will 3 * a be faster than 3.0 * a?

Your assumption is not correct because both your divide operations will be performed with two double operands. In the second case, c = a/3, the integer literal will be converted to a double value by the compiler before any code is generated.
From this Draft C++ Standard:
8.3 Usual arithmetic conversions          [expr.arith.conv]
1    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:
…
(1.3) –
Otherwise, if either operand is double, the other shall be converted
to double.
Note that, in this Draft C11 Standard, §6.3.1.8 (Usual arithmetic conversions) has equivalent (indeed, near-identical) text.

There is no difference. The integer operand is implicitly converted to a double, so they end up practically equivalent.

Related

Is there an implicit type promotion in "float = float - float"?

We are using QA-C for MISRA C++ conformance, but the tool spews out an error for code like this:
float a = foo();
float b = bar();
float c = a - b;
As far as I understand, this has no implicit type promotion as everything will happen in float-sized chunks, but the tool tells me that the subtraction causes one. Is there any situation where there might be implicit promotion?
There is no implicit promotion involved here.
When conversions involving binary operators are involved, they are called usual arithmetic conversions.
From C++ standard, [expr]/11:
11 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:
...
(11.4) — Otherwise, if either operand is float, the other shall be converted to float.
Since both operands are float in your example, there is no such conversion or promotion.
So this could be a false positive from the tool.

Why Implicit Cast from double to float available?

In C++ we can write something like
float f = 3.55;
and it is a legal statement, whereas the type of real number numerals is double and we are storing that double into floating point number. It essentially means storing 8 bytes into 4 bytes (a possible data loss)? My question is that when I write
long l = 333;
int y = l;
I get an error because long value is converted into int value (possible data loss). but why don't I encounter a problem when storing 8 byte double real numeral in floating point (4 byte)?
From §4 Standard conversions [conv] C++11:
Standard conversions are implicit conversions with built-in meaning.
Clause 4 enumerates the full set of such conversions. A standard
conversion sequence is a sequence of standard conversions in the
following order:
...
Zero or one conversion from the following set: integral promotions,
floating point promotion, integral conversions, floating point
conversions, floating-integral conversions, pointer conversions,
pointer to member conversions, and boolean conversions.
So conversion between two numeric types is allowed implicitly as it makes sense also if used carefully. For example When you calculate Amount(int) from P(int), R(float) and T(int);
And from §4.8 Floating point conversions [conv.double],
A prvalue of floating point type can be converted to a prvalue of
another floating point type. If the source value can be exactly
represented in the destination type, the result of the conversion is
that exact representation. If the source value is between two adjacent
destination values, the result of the conversion is an
implementation-defined choice of either of those values. Otherwise,
the behavior is undefined.
The conversions allowed as floating point
promotions are excluded from the set of floating point conversions.
It appears double to float conversion is implicitly performed by the compliant C++ compiler. (At the cost of potentially loosing the precision)
Your example is not an error and should compile.
When you assign a larger integer type to a smaller integer type (or perform any conversion that doesn't quality as a promotion), an integral conversion occurs and precision may be lost.
Similarly, floating point conversion occurs when you assign one floating point type to another floating point type; the result is either the same value, or a value close to it, unless the source value exceeds the range of the destination type.

About comparing an integer and a float/double in C/C++

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:
How safe is it to compare the result of an arithmetic operation on ints to a float given the situation above?
Is it necessary to (float)m_intValue1 - (float)m_intValue2 > m_floatValue for this situation?
Where in the C / C++ standard can I find a line about exactly this situation?
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 :) )
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.
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.
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.
See answers to 2. and 3.
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

ceil() and floor() functions in C++ for size_t types

I have two variables:
size_t a = 63;
size_t b = 32;
I called the function ceil(a/b). Naturally I would assume that the answer returns 2 but instead it returns 1.
I'm puzzled. I have tried casting the variables to a double or int and it doesn't seem to help.
Thanks for any help.
Let's break down what happens when you do ceil(a/b). First, an integer division happens between a and b, so 63/32 becomes (int)1, and then this 1 is casted to double to become 1.0, and then ceil(1.0) is of course just 1.0.
If you expect to get 2, you need to convert to double before the division occurs, i.e. ceil(double(a) / double(b)) uses double division.
The ceil and floor functions work on double types. You have done an integer division (because size_t is an integer type), so the result is an integer (ie it's already a whole number, so you cannot round up or down). Try casting to double before the division:
ceil( double(a) / double(b) );
floor( double(a) / double(b) );
You technically only need to cast the first one, because then you will get floating-point division instead. But it's good to be explicit and cast both.
Both 63 and 32 are ints, hence the result will be an int (i.e. 1 and not 1.96875).
Either typecast it as specified by paddy or
or use double values
ceil(63.0/32); // promotes 32 from int to double since one of the operand(63.0) is double.
ceil(63.0/32.0); // both operands are doubles
a/b will perform an integer division since they are integral types, which will result in 1, this explains why std::ceil returns the value you are seeing. if we look at the draft C++ standard section 5.6 Multiplicative operators paragraph 4 says(emphasis mine):
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. For integral operands the / operator yields the algebraic quotient with any fractional part discarded;[...]
casting either of the operands to double will be sufficient due to arithmetic conversions which are covered in section 5 Expressions paragraph 10 which says(emphasis mine):
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:
and includes this bullet:
Otherwise, if either operand is double, the other shall be converted to double.
So the following expression will yield the result you desire:
std::ceil( double(a)/b)

Why does unary minus perform integral promotion?

const auto min = -std::numeric_limits<T>::max();
T x = min; // conversion from 'const int' to 'short', possible loss of data
T is a template argument, a short in this case. Unary minus apparently performs integral promotion.
Why does unary minus perform integral promotion?
If auto is changed to T no warning is generated, but it should be assigning an int to a short. Why isn't there a warning (it could be VS being fancy)?
Short answer: (now long because people want to be excessively pedantic about English which by its very nature is not exact).
Its not explicitly (as in the unary minus mathematical).
But as part of any operation (this includes unary minus operation) on POD data there is an implicit check on input parameters (the smallest integer type that can be used in and operation is int) so there is integral promotion on the input before the unary minus (the mathematical part not the operation part). The output of all operations on POD is the same as the input parameters (after integral promotion is applied). Thus here the output is also an int.
Long answer:
In C (and thus C++) the smallest type that POD operations happen on is int. So before the unary minus is applied the value is converted to int. Then the unary minus is applied. The result of the expression is thus int.
See here: Implicit type conversion rules in C++ operators
Unary minus performs integral promotion because all the arithmetic operators on integral types do it. This convention was probably established for performance reasons (typically int was the size best suited for integral operations on the hardware) and perhaps because it's sometimes useful not to be limited to the range of smaller integral types.
I've seen bugs where people do:
uint64_t i = 1 << 33; // use 64-bit type to ensure enough bits to hold the result
But this is a bug because the result of 1 << 33 doesn't depend on what it's assigned to. (Today we have warnings about this). The solution, which is ugly, is to manually force one of the operands to be large enough: uint64_t i = static_cast<uint64_t>(1) << 33
Integral promotion happens to avoid the same sort of bug with smaller types, which would have been the common case back when C was designed this way:
short a = 30000, b = 20000
int i = a + b;
In any case "It doesn't have to be logical. It's the law."
I think this is to account for ideal computer model, which C/C++ assume. Calculations are performed in registers and it implies result's size would be machine word. Hence "automagical" expansion
I believe it's (partly) because the negative of a short may not be representable as a short.
(-215 might need promotion to int if short is 16-bit and int is bigger.)
Of course, there's no guarantee that int is any bigger, but it's (usually?) the most optimal data type for the machine anyway, so it makes sense to try promoting it to int since there's likely no performance cost anyway.