Значение выходит за границы в цикле

Вобщем есть код:

#include <iostream>
using namespace std;
int main() {
float wet = 0;
int count = 0;
while (wet < 5) {
    wet = wet + 0.1;
    count++;
    printf("Count equal %d\nwet equal %.4f\n", count,wet);
}   
}

Вопрос: Почему переменная wet выходит за пределы и становится равной 51, хотя тут нестрогое сравнение, то есть по идее она должна остановиться на 5.0 и count = 50, но при этом происходит еще одна лишняя итерация цикла

Вот что выводит


Ответы (3 шт):

Автор решения: CrazyElf

Потому что float - тип с ограниченной точностью. На самом деле на предпоследней проверке у вас в wet не ровно 5.000000000000000, а что-то вроде 4.999999999999998, но поскольку вы печатаете только 4 знака после запятой, значение при печати округляется до 5.0000 и вы этого не видите.

Поэтому числа с плавающей точкой обычно проверяют не на прямое (не)равенство другому числу, а проверяют вместо этого абсолютную разность между числами на то, что она достаточно мала (или достаточно велика).

→ Ссылка
Автор решения: 300 bucks

float и double значения надо сравнивать с некоторой точностью. Обычно рассматривают значения с некоторой малой границей эпсилон, с помощью которой эта точность и регулируется.

→ Ссылка
Автор решения: Zhihar

в дополнение ко всем написавшим выше касательно float, double и вообще любого числа с плавающей точкой

во-первых в системе числа хранятся в двоичной системе, а это значит, что дробь, которая в десятичной системе является конечной, например

1/10

в двоичной системе будет бесконечной, потому что 2^x = 10, где x - иррациональное число

поэтому, когда вы к конечной дроби добавляете бесконечную дробь, то результат будет представлять собой бесконечную дробь

1 + 0.1 = 1.1 - конечная дробь только в десятичной системе, в двоичной системе она уже бесконечная дробь

а это значит, что вы НИКОГДА не сможете достичь числа 5 от числа 1 путем сложения бесконечных дробей

поэтому вам не повезло и число было 4,999999999, а не 5 и на следующей итерации уже 5.09999999 или 5.100000000001

Чтобы понять проблему, можно зайти и с другой стороны:

представьте дробь 1/7 - в десятичной системе это 0,1428571429 (пусть число хранит 10 разрядов после запятой), а в семеричной системе это уже точное значение 0.1

и если вы решите сделать в десятичной системе

1 + 1/7 + 1/7 + 1/7 + 1/7 + 1/7 + 1/7 + 1/7

вы получите 2,0000000003

а в семеричной системе сделав тоже самое вы получите строго 2

→ Ссылка