При представлении double
число его точность в некоторой степени портит. Например, номер 37.3 может быть представлен как 37.29999999999991.
Мне нужно восстановить поврежденный double
номер (мой проект требует этого). Одним из подходов является преобразование double
в CString
,
double d = 37.3;
CString str;
str.Format("%.10f", d);
Output: str = 37.3;
Таким образом, я мог восстановить поврежденный d
, Однако я нашел контрпример. Если я установлю
d = 37.3500;
тогда его double
представление иногда будет равно 37,349998474121094. При конвертации d
в CString
выход по-прежнему 37,3499984741, что на самом деле не равно 37,3500.
Почему конвертация 37.3500 не дала желаемого ответа, а 37.3 дала? Есть ли способы восстановить double?
Благодарю.
Почему конвертация 37.3500 не дала желаемого ответа, а 37.3 дала?
Случайно. Представление 37.3
оказалось достаточно близко, чтобы округление до 10 знаков после запятой дало ожидаемый результат, в то время как 37.3499984741
не сделал.
Есть ли способы восстановить double?
Нет, когда информация потеряна, вы не сможете ее восстановить. Если вам нужно точное представление десятичных чисел, тогда вам понадобится другой формат, чем двоичная с плавающей запятой. В языке C ++ или стандартной библиотеке нет подходящего десятичного типа; в зависимости от ваших потребностей, вы можете рассмотреть такие библиотеки, как Boost.Multiprecision или же GMP. В качестве альтернативы, если вы можете ограничить количество нужных вам десятичных знаков, вы можете умножить все свои числа на этот масштаб и работать с точными целыми числами.
Это может быть сделано в некоторой степени, но не легко. Поскольку строковое представление является основанием 10, а внутренним представлением — основанием 2, при преобразовании одного в другое происходит округление. Поэтому, когда вы конвертируете десятичное число «37,35» в двойное, результат не совпадает с исходным числом. При преобразовании этого числа обратно в строку компьютер не может точно знать, какое число было там, во-первых, потому что есть несколько десятичных чисел, которые приводят к одинаковому двойному числу. Тем не менее, вы можете добавить ограничение, что вы хотите кратчайшую возможную десятичную строку, которая приводит к заданному двойному, тогда есть очень хороший шанс, что он восстановит вашу исходную строку точно. Алгоритм, использующий это ограничение, был разработан Дэвидом Гаем. Вот исходный код, вам нужны и g_fmt.c, и dtoa.c, и вот статья об этом. Это используемый по умолчанию алгоритм в Python с версии 3.1.