It is because how computer store floating point numbers. Binary floating-point cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.
When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens.
As you know computers 'think' in binary and we usually think in decimal system. But as an analogy here decimal numbers cannot accurately represent a number like 1/3, so you have to round to something like 0.33 and you don’t expect 0.33 + 0.33 + 0.33 to add up to 1, either - do you?
Similar with those floats that stored in binary are not exactly what we expect them to be but a rounded version of that.
If you need low level hadcore definition on how it is done read https://en.wikipedia.org/wiki/Floating_point but what it really means is that your float is not stored as one number but two (one is called 'significand' and the other 'exponent') and they are used to calculate your float number on the fly.