Floating-point errors occur only when there are operations whose mathematical results cannot be exactly represented in floating point. The errors are precisely defined; they are not random or arbitrary, so identical results are produced when identical operations are performed.
In your first example, you assign “27.64” to $num1 and to $num2. There is an operation being performed here: The parser must interpret the character string “27.64” and produce a floating-point result. Likely, the parser produces the floating-point number that is closest to 27.64. (As a hexadecimal floating-point numeral, that number is 0x1.ba3d70a3d70a4p+4. The part before the “p” is a hexadecimal numeral, with a fractional part. The “p4” means multiply by 24. As a decimal numeral, it is 27.6400000000000005684341886080801486968994140625.) And it produces the same number in both cases, so the comparison of $num1 to $num2 indicates they are equal to each other, although neither is equal to 27.64 (because 27.64 cannot be exactly represented in floating point).
In your second example, the floating-point number that is closest to the value of the numeral “27.60” is the same as the floating-point number that is closest to the value of the numeral “27.6”, since the two numerals represent the same value. So, again, you get identical results.
In your third example, the values of the two numerals are far apart, so you get different floating-point numbers, and the comparison indicates they are unequal.
In your fourth example, all of the values are exactly representable in floating-point, so there is no error. 25, 12.50, and 12.5 are all small multiples of a power of two (includes powers with a negative exponent, such as .5 = 2-1, within the range of the floating-point type, so they are representable. Further, the sum of 12.50 and 12.5 is exactly representable, so there is no rounding error when adding them. Thus, all the results are exact, and the comparison indicates the sum equals 25.
Problems arise when people expect identical results from two different calculations that would have the same mathematical result. A classic example is comparing “.3” to “.1+.2”. Converting the numeral “.3” to floating-point yields the closest representable value, which is 0x1.3333333333333p-2 (0.299999999999999988897769753748434595763683319091796875), slightly under .3. Converting “.1” to floating-point yields the closest representable value, which is 0x1.999999999999ap-4 (0.1000000000000000055511151231257827021181583404541015625), slightly over .1. Converting “.2” to floating-point yields the closest representable value, which is 0x1.999999999999ap-3 (0.200000000000000011102230246251565404236316680908203125), slightly over .2. Adding the latter two values yields the representable value closest to their sum, which is 0x1.3333333333334p-2 (0.3000000000000000444089209850062616169452667236328125). As you can see, that sum is different from the value obtained by converting “.3” to floating-point, so comparing them indicates they are unequal.