Related
I want to be better about knowing when I should cast. What are the implicit type conversion rules in C++ when adding, multiplying, etc. For example,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
et cetera...
Will the expression always be evaluated as the more precise type? Do the rules differ for Java?
Please correct me if I have worded this question inaccurately.
In C++ operators (for POD types) always act on objects of the same type.
Thus if they are not the same one will be promoted to match the other.
The type of the result of the operation is the same as operands (after conversion).
if:
either is long double other is promoted > long double
either is double other is promoted > double
either is float other is promoted > float
either is long long unsigned int other is promoted > long long unsigned int
either is long long int other is promoted > long long int
either is long unsigned int other is promoted > long unsigned int
either is long int other is promoted > long int
either is unsigned int other is promoted > unsigned int
either is int other is promoted > int
Otherwise:
both operands are promoted to int
Note. The minimum size of operations is int. So short/char are promoted to int before the operation is done.
In all your expressions the int is promoted to a float before the operation is performed. The result of the operation is a float.
int + float => float + float = float
int * float => float * float = float
float * int => float * float = float
int / float => float / float = float
float / int => float / float = float
int / int = int
int ^ float => <compiler error>
Arithmetic operations involving float results in float.
int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int
For more detail answer. Look at what the section §5/9 from the C++ Standard says
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 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.54)
— Then, if either operand
is unsigned long the other shall be
converted to unsigned long.
— Otherwise, if one operand is a long
int and the other unsigned int, then
if a long int can represent all the
values of an unsigned int, the
unsigned int shall be converted to a
long int; otherwise both operands
shall be converted to unsigned long
int.
— Otherwise, if either operand is
long, the other shall be converted to
long.
— Otherwise, if either operand
is unsigned, the other shall be
converted to unsigned.
[Note: otherwise, the only remaining case is
that both operands are int ]
Since the other answers don't talk about the rules in C++11 here's one. From C++11 standard (draft n3337) §5/9 (emphasized the difference):
This pattern is called the usual arithmetic conversions, which are defined as follows:
— If either operand is of scoped enumeration type, 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 shall be performed on both operands. Then the following rules shall be applied to the promoted operands:
— If both operands have the same type, no further conversion is needed.
— Otherwise, if both operands have signed integer types or both have unsigned integer types, the
operand with the type of lesser integer conversion rank shall be converted to the type of the
operand with greater rank.
— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the
rank of the type of the other operand, the operand with signed integer type shall be converted to
the type of the operand with unsigned integer type.
— Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall
be converted to the type of the operand with signed integer type.
— Otherwise, both operands shall be converted to the unsigned integer type corresponding to the
type of the operand with signed integer type.
See here for a list that's frequently updated.
This answer is directed in large part at a comment made by #RafałDowgird:
"The minimum size of operations is int." - This would be very strange
(what about architectures that efficiently support char/short
operations?) Is this really in the C++ spec?
Keep in mind that the C++ standard has the all-important "as-if" rule. See section 1.8: Program Execution:
3) This provision is sometimes called the "as-if" rule, because an
implementation is free to disregard any requirement of the Standard
as long as the result is as if the requirement had been obeyed, as far
as can be determined from the observable behavior of the program.
The compiler cannot set an int to be 8 bits in size, even if it were the fastest, since the standard mandates a 16-bit minimum int.
Therefore, in the case of a theoretical computer with super-fast 8-bit operations, the implicit promotion to int for arithmetic could matter. However, for many operations, you cannot tell if the compiler actually did the operations in the precision of an int and then converted to a char to store in your variable, or if the operations were done in char all along.
For example, consider unsigned char = unsigned char + unsigned char + unsigned char, where addition would overflow (let's assume a value of 200 for each). If you promoted to int, you would get 600, which would then be implicitly down cast into an unsigned char, which would wrap modulo 256, thus giving a final result of 88. If you did no such promotions,you'd have to wrap between the first two additions, which would reduce the problem from 200 + 200 + 200 to 144 + 200, which is 344, which reduces to 88. In other words, the program does not know the difference, so the compiler is free to ignore the mandate to perform intermediate operations in int if the operands have a lower ranking than int.
This is true in general of addition, subtraction, and multiplication. It is not true in general for division or modulus.
If you exclude the unsigned types, there is an ordered
hierarchy: signed char, short, int, long, long long, float,
double, long double. First, anything coming before int in the
above will be converted to int. Then, in a binary operation,
the lower ranked type will be converted to the higher, and the
results will be the type of the higher. (You'll note that, from
the hierarchy, anytime a floating point and an integral type are
involved, the integral type will be converted to the floating
point type.)
Unsigned complicates things a bit: it perturbs the ranking, and
parts of the ranking become implementation defined. Because of
this, it's best to not mix signed and unsigned in the same
expression. (Most C++ experts seem to avoid unsigned unless
bitwise operations are involved. That is, at least, what
Stroustrup recommends.)
My solution to the problem got WA(wrong answer), then i changed one of int to long long int and it gave AC(accept). Previously, I was trying to do long long int += int * int, and after I rectify it to long long int += long long int * int. Googling I came up with,
1. Arithmetic Conversions
Conditions for Type Conversion:
Conditions Met ---> Conversion
Either operand is of type long double. ---> Other operand is converted to type long double.
Preceding condition not met and either operand is of type double. ---> Other operand is converted to type double.
Preceding conditions not met and either operand is of type float. ---> Other operand is converted to type float.
Preceding conditions not met (none of the operands are of floating types). ---> Integral promotions are performed on the operands as follows:
If either operand is of type unsigned long, the other operand is converted to type unsigned long.
If preceding condition not met, and if either operand is of type long and the other of type unsigned int, both operands are converted to type unsigned long.
If the preceding two conditions are not met, and if either operand is of type long, t he other operand is converted to type long.
If the preceding three conditions are not met, and if either operand is of type unsigned int, the other operand is converted to type unsigned int.
If none of the preceding conditions are met, both operands are converted to type int.
2 . Integer conversion rules
Integer Promotions:
Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int. Integer promotions are applied as part of the usual arithmetic conversions to certain argument expressions; operands of the unary +, -, and ~ operators; and operands of the shift operators.
Integer Conversion Rank:
No two signed integer types shall have the same rank, even if they have the same representation.
The rank of a signed integer type shall be greater than the rank of any signed integer type with less precision.
The rank of long long int shall be greater than the rank of long int, which shall be greater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.
The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type, if any.
The rank of any standard integer type shall be greater than the rank of any extended integer type with the same width.
The rank of char shall equal the rank of signed char and unsigned char.
The rank of any extended signed integer type relative to another extended signed integer type with the same precision is implementation-defined but still subject to the other rules for determining the integer conversion rank.
For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has greater rank than T3, then T1 has greater rank than T3.
Usual Arithmetic Conversions:
If both operands have the same type, no further conversion is needed.
If both operands are of the same integer type (signed or unsigned), the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type.
If the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type.
Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. Specific operations can add to or modify the semantics of the usual arithmetic operations.
Whole chapter 4 talks about conversions, but I think you should be mostly interested in these :
4.5 Integral promotions
[conv.prom]
An rvalue of type char, signed char, unsigned char, short int, or unsigned short
int can be converted to an rvalue of type int if int can represent all the values of the source type; other-
wise, the source rvalue can be converted to an rvalue of type unsigned int.
An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2) can be converted to an rvalue of the first
of the following types that can represent all the values of its underlying type: int, unsigned int,
long, or unsigned long.
An rvalue for an integral bit-field (9.6) can be converted to an rvalue of type int if int can represent all
the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can rep-
resent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the
bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.
These conversions are called integral promotions.
4.6 Floating point promotion
[conv.fpprom]
An rvalue of type float can be converted to an rvalue of type double. The value is unchanged.
This conversion is called floating point promotion.
Therefore, all conversions involving float - the result is float.
Only the one involving both int - the result is int :
int / int = int
The type of the expression, when not both parts are of the same type, will be converted to the biggest of both. The problem here is to understand which one is bigger than the other (it does not have anything to do with size in bytes).
In expressions in which a real number and an integer number are involved, the integer will be promoted to real number. For example, in int + float, the type of the expression is float.
The other difference are related to the capability of the type. For example, an expression involving an int and a long int will result of type long int.
Caveat!
The conversions occur from left to right.
Try this:
int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0
What is a safer method to perform division:
long long / int or long long / (long long) int?
On dividing a long long by an int, can there be some security issues or any logical issues?
On dividing a long long by an int, can there be some security issues
or any logical issues?
The answer is NO with a condition that your denominator is not 0.
From the docs:
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 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.
Then, if either operand is unsigned long the other shall be converted to unsigned long.
Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.
Otherwise, if either operand is long, the other shall be converted to long.
Otherwise, if either operand is unsigned, the other shall be converted to unsigned.
[Note: otherwise, the only remaining case is that both operands are int]
So it would be like
int / int => returns int
float / float => returns float
double /double => returns double
int / double => returns double
int / float => returns float
As has already been said, going up the scale from lower to higher precision (e.g. float to double to long double, there is no problem with conversions) —each higher one in the list can hold all the values of the lower ones, so the conversion occurs with no loss of information.
For integral promotions (e.g long int and int)
If either operand is a long int, then the other one is converted to long int, and that is the type of the result.
So, this is safe (except divide by zero, of course). For more details.
I want to be better about knowing when I should cast. What are the implicit type conversion rules in C++ when adding, multiplying, etc. For example,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
et cetera...
Will the expression always be evaluated as the more precise type? Do the rules differ for Java?
Please correct me if I have worded this question inaccurately.
In C++ operators (for POD types) always act on objects of the same type.
Thus if they are not the same one will be promoted to match the other.
The type of the result of the operation is the same as operands (after conversion).
if:
either is long double other is promoted > long double
either is double other is promoted > double
either is float other is promoted > float
either is long long unsigned int other is promoted > long long unsigned int
either is long long int other is promoted > long long int
either is long unsigned int other is promoted > long unsigned int
either is long int other is promoted > long int
either is unsigned int other is promoted > unsigned int
either is int other is promoted > int
Otherwise:
both operands are promoted to int
Note. The minimum size of operations is int. So short/char are promoted to int before the operation is done.
In all your expressions the int is promoted to a float before the operation is performed. The result of the operation is a float.
int + float => float + float = float
int * float => float * float = float
float * int => float * float = float
int / float => float / float = float
float / int => float / float = float
int / int = int
int ^ float => <compiler error>
Arithmetic operations involving float results in float.
int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int
For more detail answer. Look at what the section §5/9 from the C++ Standard says
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 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.54)
— Then, if either operand
is unsigned long the other shall be
converted to unsigned long.
— Otherwise, if one operand is a long
int and the other unsigned int, then
if a long int can represent all the
values of an unsigned int, the
unsigned int shall be converted to a
long int; otherwise both operands
shall be converted to unsigned long
int.
— Otherwise, if either operand is
long, the other shall be converted to
long.
— Otherwise, if either operand
is unsigned, the other shall be
converted to unsigned.
[Note: otherwise, the only remaining case is
that both operands are int ]
Since the other answers don't talk about the rules in C++11 here's one. From C++11 standard (draft n3337) §5/9 (emphasized the difference):
This pattern is called the usual arithmetic conversions, which are defined as follows:
— If either operand is of scoped enumeration type, 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 shall be performed on both operands. Then the following rules shall be applied to the promoted operands:
— If both operands have the same type, no further conversion is needed.
— Otherwise, if both operands have signed integer types or both have unsigned integer types, the
operand with the type of lesser integer conversion rank shall be converted to the type of the
operand with greater rank.
— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the
rank of the type of the other operand, the operand with signed integer type shall be converted to
the type of the operand with unsigned integer type.
— Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall
be converted to the type of the operand with signed integer type.
— Otherwise, both operands shall be converted to the unsigned integer type corresponding to the
type of the operand with signed integer type.
See here for a list that's frequently updated.
This answer is directed in large part at a comment made by #RafałDowgird:
"The minimum size of operations is int." - This would be very strange
(what about architectures that efficiently support char/short
operations?) Is this really in the C++ spec?
Keep in mind that the C++ standard has the all-important "as-if" rule. See section 1.8: Program Execution:
3) This provision is sometimes called the "as-if" rule, because an
implementation is free to disregard any requirement of the Standard
as long as the result is as if the requirement had been obeyed, as far
as can be determined from the observable behavior of the program.
The compiler cannot set an int to be 8 bits in size, even if it were the fastest, since the standard mandates a 16-bit minimum int.
Therefore, in the case of a theoretical computer with super-fast 8-bit operations, the implicit promotion to int for arithmetic could matter. However, for many operations, you cannot tell if the compiler actually did the operations in the precision of an int and then converted to a char to store in your variable, or if the operations were done in char all along.
For example, consider unsigned char = unsigned char + unsigned char + unsigned char, where addition would overflow (let's assume a value of 200 for each). If you promoted to int, you would get 600, which would then be implicitly down cast into an unsigned char, which would wrap modulo 256, thus giving a final result of 88. If you did no such promotions,you'd have to wrap between the first two additions, which would reduce the problem from 200 + 200 + 200 to 144 + 200, which is 344, which reduces to 88. In other words, the program does not know the difference, so the compiler is free to ignore the mandate to perform intermediate operations in int if the operands have a lower ranking than int.
This is true in general of addition, subtraction, and multiplication. It is not true in general for division or modulus.
If you exclude the unsigned types, there is an ordered
hierarchy: signed char, short, int, long, long long, float,
double, long double. First, anything coming before int in the
above will be converted to int. Then, in a binary operation,
the lower ranked type will be converted to the higher, and the
results will be the type of the higher. (You'll note that, from
the hierarchy, anytime a floating point and an integral type are
involved, the integral type will be converted to the floating
point type.)
Unsigned complicates things a bit: it perturbs the ranking, and
parts of the ranking become implementation defined. Because of
this, it's best to not mix signed and unsigned in the same
expression. (Most C++ experts seem to avoid unsigned unless
bitwise operations are involved. That is, at least, what
Stroustrup recommends.)
My solution to the problem got WA(wrong answer), then i changed one of int to long long int and it gave AC(accept). Previously, I was trying to do long long int += int * int, and after I rectify it to long long int += long long int * int. Googling I came up with,
1. Arithmetic Conversions
Conditions for Type Conversion:
Conditions Met ---> Conversion
Either operand is of type long double. ---> Other operand is converted to type long double.
Preceding condition not met and either operand is of type double. ---> Other operand is converted to type double.
Preceding conditions not met and either operand is of type float. ---> Other operand is converted to type float.
Preceding conditions not met (none of the operands are of floating types). ---> Integral promotions are performed on the operands as follows:
If either operand is of type unsigned long, the other operand is converted to type unsigned long.
If preceding condition not met, and if either operand is of type long and the other of type unsigned int, both operands are converted to type unsigned long.
If the preceding two conditions are not met, and if either operand is of type long, t he other operand is converted to type long.
If the preceding three conditions are not met, and if either operand is of type unsigned int, the other operand is converted to type unsigned int.
If none of the preceding conditions are met, both operands are converted to type int.
2 . Integer conversion rules
Integer Promotions:
Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int. Integer promotions are applied as part of the usual arithmetic conversions to certain argument expressions; operands of the unary +, -, and ~ operators; and operands of the shift operators.
Integer Conversion Rank:
No two signed integer types shall have the same rank, even if they have the same representation.
The rank of a signed integer type shall be greater than the rank of any signed integer type with less precision.
The rank of long long int shall be greater than the rank of long int, which shall be greater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.
The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type, if any.
The rank of any standard integer type shall be greater than the rank of any extended integer type with the same width.
The rank of char shall equal the rank of signed char and unsigned char.
The rank of any extended signed integer type relative to another extended signed integer type with the same precision is implementation-defined but still subject to the other rules for determining the integer conversion rank.
For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has greater rank than T3, then T1 has greater rank than T3.
Usual Arithmetic Conversions:
If both operands have the same type, no further conversion is needed.
If both operands are of the same integer type (signed or unsigned), the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type.
If the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type.
Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. Specific operations can add to or modify the semantics of the usual arithmetic operations.
Whole chapter 4 talks about conversions, but I think you should be mostly interested in these :
4.5 Integral promotions
[conv.prom]
An rvalue of type char, signed char, unsigned char, short int, or unsigned short
int can be converted to an rvalue of type int if int can represent all the values of the source type; other-
wise, the source rvalue can be converted to an rvalue of type unsigned int.
An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2) can be converted to an rvalue of the first
of the following types that can represent all the values of its underlying type: int, unsigned int,
long, or unsigned long.
An rvalue for an integral bit-field (9.6) can be converted to an rvalue of type int if int can represent all
the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can rep-
resent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the
bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.
These conversions are called integral promotions.
4.6 Floating point promotion
[conv.fpprom]
An rvalue of type float can be converted to an rvalue of type double. The value is unchanged.
This conversion is called floating point promotion.
Therefore, all conversions involving float - the result is float.
Only the one involving both int - the result is int :
int / int = int
The type of the expression, when not both parts are of the same type, will be converted to the biggest of both. The problem here is to understand which one is bigger than the other (it does not have anything to do with size in bytes).
In expressions in which a real number and an integer number are involved, the integer will be promoted to real number. For example, in int + float, the type of the expression is float.
The other difference are related to the capability of the type. For example, an expression involving an int and a long int will result of type long int.
Caveat!
The conversions occur from left to right.
Try this:
int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0
Why does, for example, the result of operation between an unsigned short and int always yields an int?
unsigned short s = 65535;
int i = 65535
Expression typeid(s * i * i).name(), gives a value which is out of the range of an int but still the implicit conversion returns an int, why?
There are a set of conversions called the usual arithmetic conversions that are used prior to the evaluation of most arithmetic operators.
Basically, you can consider there to be a few rules for arithmetic on integers:
First, integer arithmetic is never performed with operands "smaller than" int, so in the case of short * signed char, both the short and the signed char operands are promoted to int, the two int values are multiplied, and then the result is an int.
Second, if one or both of the types are "larger than" int, the compiler selects a type that is at least "as large" as the type of the largest operand. So, if you have long * int, the int is promoted to a long and the result is a long.
Third, if either operand is unsigned, then the result is unsigned. So, if you have long * unsigned int, the long and the unsigned int are both promoted to an unsigned long and the result is an unsigned long.
If either operand has floating point type, then floating point arithmetic is performed: float, double, or long double is used (which one depends on the types of the operands; the full table used to determine the result type can be found on the page linked at the beginning of this answer).
Note that the result type is not dependent upon the values of the operands. The type has to be selected by the compiler at compile time, before the values are known.
If the result of s * i * i is out of range of the result type (int, in your scenario), then you're out of luck: your program can't decide at runtime, "oh, I should switch to use a long!" because the result type had to be selected at compile time.
I want to be better about knowing when I should cast. What are the implicit type conversion rules in C++ when adding, multiplying, etc. For example,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
et cetera...
Will the expression always be evaluated as the more precise type? Do the rules differ for Java?
Please correct me if I have worded this question inaccurately.
In C++ operators (for POD types) always act on objects of the same type.
Thus if they are not the same one will be promoted to match the other.
The type of the result of the operation is the same as operands (after conversion).
if:
either is long double other is promoted > long double
either is double other is promoted > double
either is float other is promoted > float
either is long long unsigned int other is promoted > long long unsigned int
either is long long int other is promoted > long long int
either is long unsigned int other is promoted > long unsigned int
either is long int other is promoted > long int
either is unsigned int other is promoted > unsigned int
either is int other is promoted > int
Otherwise:
both operands are promoted to int
Note. The minimum size of operations is int. So short/char are promoted to int before the operation is done.
In all your expressions the int is promoted to a float before the operation is performed. The result of the operation is a float.
int + float => float + float = float
int * float => float * float = float
float * int => float * float = float
int / float => float / float = float
float / int => float / float = float
int / int = int
int ^ float => <compiler error>
Arithmetic operations involving float results in float.
int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int
For more detail answer. Look at what the section §5/9 from the C++ Standard says
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 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.54)
— Then, if either operand
is unsigned long the other shall be
converted to unsigned long.
— Otherwise, if one operand is a long
int and the other unsigned int, then
if a long int can represent all the
values of an unsigned int, the
unsigned int shall be converted to a
long int; otherwise both operands
shall be converted to unsigned long
int.
— Otherwise, if either operand is
long, the other shall be converted to
long.
— Otherwise, if either operand
is unsigned, the other shall be
converted to unsigned.
[Note: otherwise, the only remaining case is
that both operands are int ]
Since the other answers don't talk about the rules in C++11 here's one. From C++11 standard (draft n3337) §5/9 (emphasized the difference):
This pattern is called the usual arithmetic conversions, which are defined as follows:
— If either operand is of scoped enumeration type, 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 shall be performed on both operands. Then the following rules shall be applied to the promoted operands:
— If both operands have the same type, no further conversion is needed.
— Otherwise, if both operands have signed integer types or both have unsigned integer types, the
operand with the type of lesser integer conversion rank shall be converted to the type of the
operand with greater rank.
— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the
rank of the type of the other operand, the operand with signed integer type shall be converted to
the type of the operand with unsigned integer type.
— Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall
be converted to the type of the operand with signed integer type.
— Otherwise, both operands shall be converted to the unsigned integer type corresponding to the
type of the operand with signed integer type.
See here for a list that's frequently updated.
This answer is directed in large part at a comment made by #RafałDowgird:
"The minimum size of operations is int." - This would be very strange
(what about architectures that efficiently support char/short
operations?) Is this really in the C++ spec?
Keep in mind that the C++ standard has the all-important "as-if" rule. See section 1.8: Program Execution:
3) This provision is sometimes called the "as-if" rule, because an
implementation is free to disregard any requirement of the Standard
as long as the result is as if the requirement had been obeyed, as far
as can be determined from the observable behavior of the program.
The compiler cannot set an int to be 8 bits in size, even if it were the fastest, since the standard mandates a 16-bit minimum int.
Therefore, in the case of a theoretical computer with super-fast 8-bit operations, the implicit promotion to int for arithmetic could matter. However, for many operations, you cannot tell if the compiler actually did the operations in the precision of an int and then converted to a char to store in your variable, or if the operations were done in char all along.
For example, consider unsigned char = unsigned char + unsigned char + unsigned char, where addition would overflow (let's assume a value of 200 for each). If you promoted to int, you would get 600, which would then be implicitly down cast into an unsigned char, which would wrap modulo 256, thus giving a final result of 88. If you did no such promotions,you'd have to wrap between the first two additions, which would reduce the problem from 200 + 200 + 200 to 144 + 200, which is 344, which reduces to 88. In other words, the program does not know the difference, so the compiler is free to ignore the mandate to perform intermediate operations in int if the operands have a lower ranking than int.
This is true in general of addition, subtraction, and multiplication. It is not true in general for division or modulus.
If you exclude the unsigned types, there is an ordered
hierarchy: signed char, short, int, long, long long, float,
double, long double. First, anything coming before int in the
above will be converted to int. Then, in a binary operation,
the lower ranked type will be converted to the higher, and the
results will be the type of the higher. (You'll note that, from
the hierarchy, anytime a floating point and an integral type are
involved, the integral type will be converted to the floating
point type.)
Unsigned complicates things a bit: it perturbs the ranking, and
parts of the ranking become implementation defined. Because of
this, it's best to not mix signed and unsigned in the same
expression. (Most C++ experts seem to avoid unsigned unless
bitwise operations are involved. That is, at least, what
Stroustrup recommends.)
My solution to the problem got WA(wrong answer), then i changed one of int to long long int and it gave AC(accept). Previously, I was trying to do long long int += int * int, and after I rectify it to long long int += long long int * int. Googling I came up with,
1. Arithmetic Conversions
Conditions for Type Conversion:
Conditions Met ---> Conversion
Either operand is of type long double. ---> Other operand is converted to type long double.
Preceding condition not met and either operand is of type double. ---> Other operand is converted to type double.
Preceding conditions not met and either operand is of type float. ---> Other operand is converted to type float.
Preceding conditions not met (none of the operands are of floating types). ---> Integral promotions are performed on the operands as follows:
If either operand is of type unsigned long, the other operand is converted to type unsigned long.
If preceding condition not met, and if either operand is of type long and the other of type unsigned int, both operands are converted to type unsigned long.
If the preceding two conditions are not met, and if either operand is of type long, t he other operand is converted to type long.
If the preceding three conditions are not met, and if either operand is of type unsigned int, the other operand is converted to type unsigned int.
If none of the preceding conditions are met, both operands are converted to type int.
2 . Integer conversion rules
Integer Promotions:
Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int. Integer promotions are applied as part of the usual arithmetic conversions to certain argument expressions; operands of the unary +, -, and ~ operators; and operands of the shift operators.
Integer Conversion Rank:
No two signed integer types shall have the same rank, even if they have the same representation.
The rank of a signed integer type shall be greater than the rank of any signed integer type with less precision.
The rank of long long int shall be greater than the rank of long int, which shall be greater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.
The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type, if any.
The rank of any standard integer type shall be greater than the rank of any extended integer type with the same width.
The rank of char shall equal the rank of signed char and unsigned char.
The rank of any extended signed integer type relative to another extended signed integer type with the same precision is implementation-defined but still subject to the other rules for determining the integer conversion rank.
For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has greater rank than T3, then T1 has greater rank than T3.
Usual Arithmetic Conversions:
If both operands have the same type, no further conversion is needed.
If both operands are of the same integer type (signed or unsigned), the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type.
If the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type.
Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. Specific operations can add to or modify the semantics of the usual arithmetic operations.
Whole chapter 4 talks about conversions, but I think you should be mostly interested in these :
4.5 Integral promotions
[conv.prom]
An rvalue of type char, signed char, unsigned char, short int, or unsigned short
int can be converted to an rvalue of type int if int can represent all the values of the source type; other-
wise, the source rvalue can be converted to an rvalue of type unsigned int.
An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2) can be converted to an rvalue of the first
of the following types that can represent all the values of its underlying type: int, unsigned int,
long, or unsigned long.
An rvalue for an integral bit-field (9.6) can be converted to an rvalue of type int if int can represent all
the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can rep-
resent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the
bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.
These conversions are called integral promotions.
4.6 Floating point promotion
[conv.fpprom]
An rvalue of type float can be converted to an rvalue of type double. The value is unchanged.
This conversion is called floating point promotion.
Therefore, all conversions involving float - the result is float.
Only the one involving both int - the result is int :
int / int = int
The type of the expression, when not both parts are of the same type, will be converted to the biggest of both. The problem here is to understand which one is bigger than the other (it does not have anything to do with size in bytes).
In expressions in which a real number and an integer number are involved, the integer will be promoted to real number. For example, in int + float, the type of the expression is float.
The other difference are related to the capability of the type. For example, an expression involving an int and a long int will result of type long int.
Caveat!
The conversions occur from left to right.
Try this:
int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0