Обнаружение потери точности при конвертации из двойного в плавающее - PullRequest
6 голосов
/ 13 июля 2010

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

Например

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

Создает dest, значение которого 1988.1

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

Ответы [ 4 ]

11 голосов
/ 13 июля 2010

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

9 голосов
/ 13 июля 2010
float dest = numeric_cast<float>(source);
double residual = source - numeric_cast<double>(dest);

Следовательно, residual содержит «потерю», которую вы ищете.

1 голос
/ 13 июля 2010

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

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

1 голос
/ 13 июля 2010

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

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

...