Округление больших чисел [c#]
Вопрос
У меня тут какая-то странная проблема.У меня есть таблица базы данных, в столбце которой хранится огромное значение.Мое приложение (С#) читает это значение и сохраняет двойной тип.Это приложение вставит то же значение в другую таблицу.Примечание :Я не выполняю никаких вычислений/обработки значения, прочитанного из первой таблицы.Он сохраняется только для обновления второй таблицы.
Проблема в том, что вторая таблица получает немного другое значение, чем первая.Похоже, число округляется, когда я сохраняю двойной тип.
Вот пример значений.
Исходное значение: 18014398509481984
Значение скопировано в новую таблицу: 18014398509482000
Значения выглядят по-разному, но на самом деле они одинаковы.Я выполнил поиск в Google с помощью 18014398509481984 - 18014398509482000 в качестве поискового запроса и он вернул результат 0, что означает, что оба одинаковы.
Вопросы:
1. Если оба одинаковы, почему второе значение выглядит по-другому?я вижу 1984 превратился в 2000.
2. Почему происходит преобразование?
3. Как избежать такого рода конверсий?
Любая помощь будет здорово!
Решение
Попробуйте использовать System.Decimal
для хранения значения из первой таблицы вместо System.Double
. System.Double
похоже, не содержит достаточно значащих цифр для точного хранения такого большого значения.
Другие советы
Значение двойной точности имеет точность только до 15 или 16 десятичных цифр (см. здесь для пояснения).Если вам нужно сохранить больше данных, вам придется использовать другой числовой формат.Если вы хотите работать с очень большими целыми числами без потери точности, существуют различные классы, которые вам помогут. Вот этот.
Если вы получаете значение из SQL, убедитесь, что ваш целевой тип данных в .NET соответствует — например, SQL bigint для C# long — чтобы избежать подобных проблем с округлением.
Я считаю, что это связано с точностью с плавающей запятой (большое число будет использовать мантиссу в качестве показателя степени), что означает, что по сути оно будет представлено как дробное число со степенью.Однако дробные числа сталкиваются с ошибками округления из-за арифметики с плавающей запятой.
Обычно обходной путь заключается в том, чтобы избегать значений с плавающей запятой (попробуйте Int64), использовать более точный тип (десятичный) или учитывать ошибку и выполнять «приблизительно равно».