У меня есть какая-то странная проблема. У меня есть таблица базы данных, которая имеет огромное значение, хранящуюся в столбце. Мое приложение (С#) считывает это значение и сохраняется в двойном типе. Это приложение будет вставлять то же значение в другую таблицу. Примечание. Я не делаю никаких вычислений/обработки значения, считанного из первой таблицы. Он просто хранится для обновления второй таблицы.
Проблема здесь, вторая таблица получает немного другое значение, чем в первой таблице. Похоже, что число округляется, когда я держусь в двойном типе.
Вот пример значений.
Исходное значение: 18014398509481984
Значение, скопированное в новую таблицу: 18014398509482000
Значения выглядят по-разному, но в действительности они одинаковы. Я выполнил поиск в google с 18014398509481984 - 18014398509482000 как поисковый запрос, и он вернул результат 0, что означает, что оба они одинаковы.
Вопросы
1 - Если оба одинаковы, почему второе значение выглядит иначе? Я могу видеть 1984 в 2000.
2 - Почему происходит преобразование?
3 - Как избежать этого типа преобразований?
Любая помощь будет замечательной!
Попробуйте использовать System.Decimal
для сохранения значения из первой таблицы вместо System.Double
. System.Double
, похоже, не содержит достаточно значимых цифр, чтобы точно хранить это значение.
Значение двойной точности является точной только для 15 или 16 десятичных цифр (см. здесь для объяснения). Если вам нужно сохранить больше, чем это, вам придется использовать другой формат номера. Если вы хотите работать с очень большими целыми числами без потери точности, тогда есть различные классы, которые помогут вам этот.
Если вы получаете значение из SQL, убедитесь, что ваш целевой тип данных в .NET соответствует - SQL bigint для С# long, например, чтобы избежать проблем округления, подобных этому.
Я считаю, что это связано с точностью с плавающей запятой (большое число будет использовать мантисса экспонента), что означает, что он будет по существу представлен как фракционное число с мощностью. Однако дробные числа сталкиваются с ошибками округления из-за арифметики с плавающей запятой.
Обычно, чтобы избежать значений с плавающей запятой (попробуйте Int64), используйте более точный тип (десятичный) или учетную запись для ошибки и сделайте "приблизительно равным".
Нужно ли хранить их как числа с плавающей запятой?
Если нет, вы можете вместо этого использовать 64-битные целые числа: BIGINT
в базе данных и long
/Int64
в вашем приложении.
Они имеют диапазон от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807 и не имеют проблем с точностью и точностью.