*P.S: Acabou que demorou tanto tempo pra explicar que quando terminei a resposta já tinha uma resposta mais bem elaborada acima, rs... Como não sei como excluir postagem, fica aí a tentativa! *
Essa história de float é uma história bem comprida... Já li umas três vezes e sinceramente, acho que vale a pena saber só por alto.
O negócio é que o espaço em memória para guardar um número com ponto flutuante preciso seria indesejavelmente grande. Geralmente a gente não precisa de uma precisão absurda quando estamos lidando com número fracionários (que é o objetivo do float), então encontraram uma fórmula matemática que permite armazenar o valor aproximado de um número fracionado utilizando-se razoavelmente poucos termos em uma equação exponencial. Essa equação no entanto não é o número preciso em sí, e ela tende a gerar o "ruído" que você observou nos seus experimentos.
A fórmula separa qualquer número em três termos: 1- A parte fracionária (mantissa); 2- Uma base; 3- Um expoente.
Se procurar no wikipédia, eles dão alguns exemplos de números criados a partir desta fórmula (MANTISSA x BASE ^ (elevado a EXPOENTE)), mas sinceramente, acho que isso é mais útil a título de curiosidade e compreensão do que se passa do que para aplicação prática (deixa o computador usar as fórmulas dele, kkk).
Geralmente, a utilização de qualquer método de arredondamento para 1, 2 ou 3 casas decimais antes de fazer comparações é suficiente para resolver este problema. O problema é que esse ruído tende a aumentar quantos mais operações são feitas com o valor. Então se pegar o mercado financeiro, por exemplo, onde esse ruído vai ser multiplicado, subtraído, dividido e somado inúmeras vezes, ele acaba por tornar-se inaceitável.
A solução vai variar do contexto, embora sempre venha a algum custo. O próprio float sacrifica precisão em prol de menor ocupação de memória (mais necessário em situações em que o processamento é limitado, como era o caso em máquinas antigas).
No mercado financeiro, exemplo comumente usado pra explicar essa questão, o Python utiliza-se do Decimal ao invés de float pra cálculos. A troca nesse caso é que float é um tipo primitivo (utiliza apenas 4 bytes e tem uma sintaxe bem simples e intuitiva), e o Decimal é uma classe com método próprio, e ocupação significativamente maior em memória (mas não tanto que venha a afetar de maneira perceptível cálculos financeiros, por exemplo). A declaração de um Decimal é feita de forma diferente à que seria usada para um tipo primitivo, o que pode parecer uma complicação desnecessária a início tmb... A declaração poderia ser, por exemplo, "Decimal('0.123')"... Mas a não ser que você realmente precise desse nível de precisão, dificilmente você vai usar essa classe.
Outra solução é utilizar números inteiros e considerar deslocamento na hora de enviar o resultado final pro cliente (por exemplo, se deseja 3 casas decimais, considera que 100 é 0.1, que 1000 é 1, etc... Na hora de printar o resultado, divide o número por 1000, operando apenas uma vez com ponto flutuante e garantindo razoavel precisão).
Enfim, essa imprecisão do float geralmente não afeta programas simples e float ainda é a maneira mais direta de utilizar números fracionados no aprendizado, mas sabendo dessa perda de precisão, a solução para o problema vai depender do contexto de cada programa e da viabilidade de se usar arredondamentos, mais processamento, etc.
Não entrei em detalhes maiores porque acho que esse assunto é um pouco enfadonho, e de minha parte pelo menos, matei minha curiosidade com um entendimento superficial a primeira vez que me deparei com o problema... Mas se quiser cavar a fundo, você já sabe por onde começar, ao menos!