A comparison between double and float gets float implicitly converted to double. Which means that your a==b is interpreted as (double) a == b.
The fractional part of 4.5 is an exact power of 2: 0.5 == 2-2. This value is represented in binary floating-point format precisely
4.5 dec = 100.1 bin
And it is represented precisely in both double and float. So, the comparison compares 4.5 to 4.5 and the result is true.
4.2 is requires an infinite periodic sum of powers of 2 to represent.
4.2 dec = 100.0011001100110011... bin = 100.(0011) bin
For this reason it is represented in double and float only approximately - the infinite sequence gets trimmed in one way or another. Since float has less precision than double, the value stored in float ends up being different than the value stored in double. In double you get something like 4.1999998092651367, while in float you get something like 4.2000000000000002. The conversion to double in (double) a == b cannot make the values to "match" and the result is false.