Обнаружение потери точности при преобразовании из double в float

Я пишу кусок кода, в котором мне нужно преобразовать из Double в float значения. Я использую boost:: numeric_cast для этого преобразования, которое предупредит меня о любом переполнении/подаче. Однако мне также интересно узнать, привело ли это преобразование к некоторой потере точности или нет.

    double source =  1988.1012;
    float dest = numeric_cast<float>(source);

производит dest, который имеет значение 1988.1

есть ли какой-либо способ, которым я могу обнаружить такую точность потеря / округление

4 ответов


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


float dest = numeric_cast<float>(source);
double residual = source - numeric_cast<double>(dest);

отсюда residual содержит "потерю", которую вы ищете.


посмотрите на эти статьи для один и двойной точности поплавки. Прежде всего, поплавки имеют 8 бит для экспоненты против 11 для двойника. Таким образом, все, что больше 10^127 или меньше 10^-126 по величине, будет переполнением, как вы упомянули. Для float у вас есть 23 бита для фактических цифр числа, против 52 бит для double. Таким образом, очевидно, что у вас намного больше цифр точности для double, чем float.

скажем, у вас есть номер, как: 1.1123. Это число на самом деле не может быть закодировано как 1.1123, потому что цифры числа с плавающей запятой используются для фактического сложения как дроби. Например, если бит в мантиссе были 11001, тогда значение будет сформировано из 1 (неявные) + 1 * 1/2 + 1 * 1/4 + 0 * 1/8 + 0 * 1/16 + 1 * 1/32 + 0 * (64 + 128 + ...). Поэтому точное значение не может быть закодировано, если вы не можете сложить эти дроби таким образом, чтобы это было точное число. Это редкий. Поэтому почти всегда будет потеря точности.


У вас будет определенный уровень потери точности, согласно ответу Дэйва. Если, однако, вы хотите сосредоточиться на его количественном определении и создании исключения, когда оно превышает определенное число, вам придется открыть само число с плавающей запятой и проанализировать мантиссу и показатель, а затем сделать некоторый анализ, чтобы определить, если вы превысили допуск.

но, хорошая новость, его обычно стандартный поплавок с плавающей запятой IEEE. :-)