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 int1 / (i + 1) returns int for the same reason1 / (i + 1), which is an int, is statically cast to doubleOTOH in result = 1 / (i+static_cast<double>(1)) it's like this
1 is cast to doublei + 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 ofcharis equal to the rank ofsigned charandunsigned char. The ranks ofchar8_t,char16_t,char32_t, andwchar_tare equal to the ranks of their underlying types.