In this video, we'll learn about mixed type expressions.
This is when you have an expression where the operands are of different types.
For example, a plus b where a is an integer and b is a double.
C++ is very consistent with its application of an operator to operands.
The operands must be of the same type.
As we'll see in the next few slides,
it's very important to understand the rules that c++ uses
to ensure that the types are the same since the results of the calculation
could be different depending on which operand type is changed.
C++ will try to convert one of the operands so it matches the other.
In many cases, this happens automatically, and we'll talk about how that works in the next slide.
If an automatic conversion or coercion is not possible,
then a compiler error will occur.
We saw an example of this in the assignment operator video
when we tried to assign a string to an integer.
In order to understand how these conversions happen,
we need to understand higher versus lower types.
The idea is simple.
The lower types are those types that can hold smaller values
and the higher types can hold larger values. So a long double
is of higher type than a long and a long is of higher type than an int.
The idea is that we can typically convert
from a lower type to a larger type automatically
since the lower types value will fit into the higher types value
but the opposite may not be true.
Short and character types are always converted to integers.
So let's learn the terminology.
A type conversion is also called a coercion
since we're coercing one type to another.
Sometimes this happens automatically and sometimes we do it ourselves in code.
Promotion is when we convert a lower type to a higher type.
An example would be when we add an integer and a double.
In this case, we promote the integer to a double and then do the calculation.
Demotion is when we convert a higher type to a lower type.
Suppose we want to store 12.5 into an integer variable.
It won't fit. So a demotion happens, and the decimal part of
12.5 is truncated,
and we're left just with the integer 12.
Let's see a few examples.
In the first example, we have two different types
and an operator.
You can think of the operator as the multiplication operator
but it applies to any operator.
In order to perform the multiplication,
the compiler will convert the lower type to the higher type
and then perform the multiplication.
You can see in the example where we multiply the integer
2 and the double 5.2.
In this case, we can promote the lower type, which is the integer 2
to the double 2.0 and then perform the multiplication.
In the second example, we're assigning a value from a higher type to a lower type.
In this case, the compiler demotes the higher type to the lower type,
potentially losing information.
Many compilers will warn you about the possible loss of precision but not all do.
In this example,
we have num as an integer and we assign a double 100.2 to num.
100.2 will be demoted to the integer 100,
and 100 will be assigned to num.
As mentioned previously,
the c++ compiler will try to do automatic coercion when it can.
However, as programmers, we can explicitly tell the compiler
to cast to a specific type if we wish. Let's see how.
So let's talk about how we can tell the compiler to coerce or cast one type to another.
Let's walk through this example.
You can see we have two integer variables.
Think of total amount as a running sum of several numbers
and we want to know the average of those numbers.
So we need to know how many numbers there are.
In this case, this is represented by the integer total number which is 8.
The average in this case would be total amount divided by total number,
which is 12.5.
But since both of these variables are integers,
the compiler will do integer division, and the result will be 12.
That's not what we want.
We could change the type of total amount to double,
but we're modeling a running total of integers. So an integer type is more appropriate.
The solution is for us to tell the compiler to cast
or perform a coercion of total amount from integer to double.
The syntax is to use static underscore cast,
followed by the type we want to convert to in angle brackets
and then the variable name in parentheses.
Now one of the operands is a double so the compiler will automatically convert
the total number to a double and do double division, which is exactly what we want.
Now we get 12.5, which is the result we wanted.
Let's head over to CodeLite and write a program that asks the user for three integers
and computes their average.
Okay. So now I'm in the CodeLite IDE. I'm in the section 8 workspace
in the mixed expressions project.
So let's write a program here that asks the user to enter three integers.
We calculate the sum of those integers, and then we calculate the average of the integers.
All right. Then at the end, we'll just display the three integers that were entered,
the sum of the integers and the average that we calculated.
All right. So let's get started.
We have an empty main here,
and I'll scroll this up so we have a little bit more room to work.
And we know we need a total, right. We need to sum up those three numbers,
but we also need to store those three numbers.
So let's create those variables first. We'll create a total variable.
And again, the names you use could be anything you like and we'll zero that out.
And we'll create three variables for the numbers that we're going to enter.
We'll call them num1
and I could do this and do each one on each line.
But what I'm going to do is I'm just going to do them all in one line.
So I'm going to say num1 and I'm going to say num2.
And finally, I'll say num3.
This initializes all three of them to zero.
If you don't do it this way
or rather if you do it this way and you don't
put those initializers there,
then num3 will be 0 and num1 and num2 will be undefined.
So if you do it this way be certain that each one of them gets its own initializer.
So that's it. We've got our three numbers.
We've got our total, and
we also need a count, right. We're going to have three numbers. We might, as well,
define that integer as a const,
and we'll call it count. And again, we'll initialize that to three.
That way we know we're not going to make any silly mistakes.
Great. So let's prompt the user. We'll say cout,
and I'll just say "Enter 3 integers
separated by spaces"
That way they could just type them in on one line. We don't have to do three prompts.
And we'll just leave it at that, don't forget the semicolon at the end.
We don't need an endline here.
Now we're going to read all three integers. So we'll do cin.
We'll use the extraction operator num1 and we'll just chain them together
num2 and num3.
All right. So now we've got all three of our integers.
We need to total them up now right. We need to sum them all up,
so we've got our total variable.
So we'll just say total is num1
plus num2 plus num3.
All right. So now we've got that. Now obviously, we could have total
be a double.
But it really makes sense for it to be integers
because we're adding up integers so the total should be an integer.
So now let's calculate the average.
We need a variable to hold that. So it that will be a double,
and we'll just call it average. And let's initialize that to 0.0.
That way we know we've got a known value in there.
Great. So let's do the calculation now.
Average and I'm just using some blank lines here just to separate them.
Normally, you wouldn't write all these blank lines but I just want to write them so you can really see what's going on.
So I'll say average
is the total
divided by count.
That's it. And now we've got our output statements. We'll say,
let's just say, something like the three numbers were
and we'll display all three numbers here. We'll say num1,
we'll put a comma here.
We'll say num2,
we'll put another comma and finally num3
followed by the endline.
Next statement we'll say the sum.
The sum of the numbers is
and obviously that is our total variable.
So we'll display total here.
And again, we'll follow it by an endline.
And then finally, the average.
There's my last output statement and we'll just say the average
of the numbers is
and again average.
Okay, so far so good,
endline. That's it.
Let's compile this and see if we've got any compiler errors that we have to fix.
Okay. No compiler errors. It runs so let's run this.
Enter three integers separated by spaces.
How about 10, 30 and 20
right, that's 40, 50, 60. 60 divided by 3 is going to give me 20.
So I expect that to be the average. I'll press enter. The output says
the three numbers were 10, 30, 20. That's correct.
The sum of the numbers is 60, that's correct.
The average of the numbers is 20, that's also correct.
Okay. One more test case. We'll say 10,
20, 15.
In this case, we've got
45. The average is 15.
Good, we're done. No, we're not. Program has a
pretty big problem in it and we saw that in the slides.
Suppose that I run it again
with a different test case, something like 10, 20, 20.
In this case, it's 50 divided by 3, which is 16.667.
Instead, I'm getting 16 because I'm doing integer division.
This is why testing your program is so important.
We'll talk about testing as we go through the course, but testing your program is important.
And testing involves knowing what the result is before you run your program,
right. So in this case have some test cases ready,
maybe 0, 0, 0. Something that is divisible evenly by three.
Another test case that isn't divisible by three and so forth. Okay
so how do we fix this. Well, what we can do is
we can cast that guy or this guy either one to a double.
Okay, and we'll use the static cast. So we'll say static
underscore cast.
Then in the angle brackets, we put in the type that we want to cast to.
In this case, I want to cast it to a double or convert it to a double.
And then we put total inside parentheses.
That's it. Now what's going to happen is the compiler will convert total to a double.
The compiler will say oh I want to do -- I've got a double and an integer here
so I'll convert the integer to a double as well
and do double division, which is what we want so
let's run this again
and let's use that same test case; 10, 20, 20.
And now we've got the correct average here.
Okay.Now before I finish this video off, in
older c code,
instead of seeing this static cast here,
you might have seen something that looked like this,
something like that, then total
divided by count or something like that.
Okay. This is the old c style cast.
The static cast is what we want to be using in modern c++.
It's a little bit more restrictive than this kind of cast. This kind of cast just assumes that
whatever total is, is going to be converted to a double.
The static cast double checks to make sure that it can be converted to a double.
So you don't want to do this.
I'll just write here it's a comment old style. Just so if you've seen it,
you'll know what it's all about.
Okay. So that's it. That's the example. Pretty straightforward.
We're defining some variables, we're getting some input,
we're doing some calculations.
And then we're checking that calculation to be sure it's correct.
In this case, I've got integer, integer division.
I've got to make one of those a double. Otherwise, I'm not going to get the right result.
Okay that's it for this video.