Неточные вычисления в C++
Дробный счет иногда расходится с обычной
арифметикой. На экран сумма выходит привычной,
а проверка в if эту привычную дробь
не узнает.
В битах дробь собирается из половин, четвертей,
восьмых и таких же следующих долей. Если число
складывается из этих долей без хвоста, оно лежит
в памяти точно. 0.5 - это половина,
0.25 - четверть:
double num = 0.5 + 0.25;
std::cout << num << "\n"; // выведет 0.75
Десятая доля из таких кусков не складывается.
В десятичной записи не кончается 1/3,
в битах так же не кончается 0.1.
В double помещается ближайшее значение
примерно на 15 значащих цифр.
У float цифр около 7, зазор крупнее.
На экран 0.1 все равно выходит коротко:
double num = 0.1;
std::cout << num << "\n"; // выведет 0.1
Зазор проявляется в действии. Складываются не
написанные десятые, а ближайшие значения из байтов.
Их сумма не совпадает с тем, как в памяти лежит 0.3.
Обычный вывод все равно показывает 0.3.
Проверка равенства уходит в другую ветку:
double num = 0.1 + 0.2;
std::cout << num << "\n"; // выведет 0.3
if (num == 0.3) {
std::cout << "Y" << "\n";
} else {
std::cout << "N" << "\n"; // сработает это
}
Вычитание устроено так же. Разность может не совпасть с привычной десятой. На экране снова короткая запись, а ветка равенства не срабатывает:
double num = 0.3 - 0.1;
std::cout << num << "\n"; // выведет 0.2
if (num == 0.2) {
std::cout << "Y" << "\n";
} else {
std::cout << "N" << "\n"; // сработает это
}
Умножение перемножает хранимые значения, а не школьные десятые:
double num = 0.1 * 3.0;
std::cout << num << "\n"; // выведет 0.3
if (num == 0.3) {
std::cout << "Y" << "\n";
} else {
std::cout << "N" << "\n"; // сработает это
}
Зазор виден не в каждом действии. Иногда сумма двух приближенных чисел совпадает с привычным результатом и в памяти. Тогда срабатывает первая ветка:
double num = 0.1 + 0.1;
std::cout << num << "\n"; // выведет 0.2
if (num == 0.2) {
std::cout << "Y" << "\n"; // сработает это
} else {
std::cout << "N" << "\n";
}
Даны две переменные:
double num1 = 0.1;
double num2 = 0.7;
Найдите сумму и выведите ее.
Если сумма равна 0.8, выведите
"Y", иначе "N".
Даны две переменные:
double num1 = 0.2;
double num2 = 0.1;
Найдите сумму и выведите ее.
Если сумма равна 0.3, выведите
"Y", иначе "N".
Даны две переменные:
double num1 = 0.25;
double num2 = 0.25;
Найдите сумму и выведите ее.
Если сумма равна 0.5, выведите
"Y", иначе "N".
Даны две переменные:
double num1 = 0.3;
double num2 = 0.2;
Найдите разность: вычтите вторую из первой и выведите ее.
Если разность равна 0.1, выведите
"Y", иначе "N".
Даны две переменные:
double num1 = 0.4;
double num2 = 0.1;
Найдите разность: вычтите вторую из первой и выведите ее.
Если разность равна 0.3, выведите
"Y", иначе "N".
Даны две переменные:
double num1 = 0.1;
double num2 = 0.2;
Найдите произведение и выведите его.
Если произведение равно 0.02, выведите
"Y", иначе "N".
Даны две переменные:
double num1 = 0.2;
double num2 = 3.0;
Найдите произведение и выведите его.
Если произведение равно 0.6, выведите
"Y", иначе "N".
Даны две переменные:
double num1 = 0.5;
double num2 = 0.5;
Найдите произведение и выведите его.
Если произведение равно 0.25, выведите
"Y", иначе "N".
Даны три переменные:
double num1 = 0.1;
double num2 = 0.2;
double num3 = 0.3;
Найдите сумму и выведите ее.
Если сумма равна 0.6, выведите
"Y", иначе "N".