Why does
result = static_cast<double>(1 / (i+1))
return int
in C++ and why does
result = 1 / (i+static_cast<double>(1))
return double
? Specifically why is casting after the +
-operation sufficient to produce a double
. Why is it not required before the +
or in the numerator as well? Is static_cast
the preferred way of casting?
Code:
double harmonic(int n) {
double result = 0;
for (int i = 0; i < n; i++) {
result += 1 / static_cast<double>(i+1);
}
return result;
}
There's no such thing as "casting order" because the type of an expression depends on its operands. Put it simply, if a binary arithmetic operator accepts two operands of different types then the smaller type will be implicitly converted to the wider type
In result = static_cast<double>(1 / (i+1))
it's parsed like this
i + 1
is an int
expression since both i
and 1
are of type int
1 / (i + 1)
returns int for the same reason1 / (i + 1)
, which is an int
, is statically cast to double
OTOH in result = 1 / (i+static_cast<double>(1))
it's like this
1
is cast to double
i + static_cast<double>(1)
returns double
because i
is upconverted to double
due to the higher rank of the other operand1 / (i+static_cast<double>(1))
is a double
expression for the same reason. It's also a floating-point division instead of an integer division like in the other caseBut don't cast like that. It's better to do 1 / (i + 1.0)
or 1.0 / (i + 1)
instead
The complete rule is like this
- If either operand has scoped enumeration type, no conversion is performed: the other operand and the return type must have the same type
- Otherwise, if either operand is
long double
, the other operand is converted tolong double
- Otherwise, if either operand is
double
, the other operand is converted todouble
- Otherwise, if either operand is
float
, the other operand is converted tofloat
- Otherwise, the operand has integer type (because
bool
,char
,char8_t
,char16_t
,char32_t
,wchar_t
, and unscoped enumeration were promoted at this point) and integral conversions are applied to produce the common type, as follows:
- If both operands are signed or both are unsigned, the operand with lesser conversion rank is converted to the operand with the greater integer conversion rank
- Otherwise, if the unsigned operand's conversion rank is greater or equal to the conversion rank of the signed operand, the signed operand is converted to the unsigned operand's type.
- Otherwise, if the signed operand's type can represent all values of the unsigned operand, the unsigned operand is converted to the signed operand's type
- Otherwise, both operands are converted to the unsigned counterpart of the signed operand's type.
The conversion rank above increases in order
bool
,signed char
,short
,int
,long
,long long
. The rank of any unsigned type is equal to the rank of the corresponding signed type. The rank ofchar
is equal to the rank ofsigned char
andunsigned char
. The ranks ofchar8_t
,char16_t
,char32_t
, andwchar_t
are equal to the ranks of their underlying types.