Сокращение количества цифр после запятой в float на C++
Есть float, который имеет значение от 0.0 до 1.0, он приобретает значение 0.666666 Нужно сделать так чтобы после . было только 4 цифры, пробуя реализовать разные способы на VSCode, ничего не получается, что я пробовал:
- через деления с умножением
- через round и т.п.
- через перевод через строку
- через разбиение на массив чаров и перевод обратно
- через функцию, которая разбивает число на целое и остаток
Все попытки заканчивались тем что float вспоминал свое старое значение и возвращался в исходное состояние
Ответы (1 шт):
В самой переменной 'float' невозможно хранить, ни 0.666666, ни 0.6667 (или 0.6666 в зависимости от того, что назвать требуемыми 4-мя цифрами). Можно хранить, только ближайшие к ним числа.
#include <cmath>
#include <iostream>
#include <limits>
using namespace std;
int main() {
cout.precision(numeric_limits<float>::max_digits10);
float in = 0.666666f;
cout << "Вход Согласно IEEE: " << in << '\n';
cout << "Предыдущее и последующее float: "
<< nextafterf(in, 0.) << ", "
<< in << ", "
<< nextafterf(in, INFINITY) << "\n\n";
float x = round(in*10000.)/10000.;
cout << "Выход Согласно IEEE: " << x << '\n';
cout << "Предыдущее и последующее float: "
<< nextafterf(x, 0.) << ", "
<< x << ", "
<< nextafterf(x, INFINITY) << "\n\n";
return 0;
}
Печатает:
$ clang++ x666.cpp && ./a.out
Вход Согласно IEEE: 0.666665971
Предыдущее и последующее float: 0.666665912, 0.666665971, 0.666666031
Выход Согласно IEEE: 0.666700006
Предыдущее и последующее float: 0.666699946, 0.666700006, 0.666700065
И действительно, 0.666700006 ближе к 0.6667, чем 0.666699946.
P.S.
Строго говоря, в операции float x = round(in*10000.)/10000. есть одна маловероятная засада, in*10000. выполняется точно, round(...)/10000. вычисляется с округлением типа double, присвоение округляет результат до float, и при крайне неудачном сочетании этих округлений, можно получить не самое ближайшее значение float, а соседнее.
Т.е. такой код не следует использовать там, где нужна гарантированная точность, к примеру, при печати многозначных чисел и т.п.
Но в данном случае, нам повезло.
P.P.S.
С точки зрения математики, для понимания вышеприведённого кода, описания стандартной функции nextafterf() достаточно, но, как советуют, невредно прочитать и человеческим языком: Число одинарной точности по IEEE, оно же, обычно, float
P.P.P.S.
Извините, исправил опечатку, код был с округлением до 4-х цифр, если нужны просто первые 4 цифры, т.е. в результате ближайшее к 0.6666, то следует использовать trunc(in*10000.)/10000..