Большие числа округляются [c #]

2

У меня есть какая-то странная проблема. У меня есть таблица базы данных, которая имеет огромное значение, хранящуюся в столбце. Мое приложение (С#) считывает это значение и сохраняется в двойном типе. Это приложение будет вставлять то же значение в другую таблицу. Примечание. Я не делаю никаких вычислений/обработки значения, считанного из первой таблицы. Он просто хранится для обновления второй таблицы.

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

Вот пример значений.

Исходное значение: 18014398509481984

Значение, скопированное в новую таблицу: 18014398509482000

Значения выглядят по-разному, но в действительности они одинаковы. Я выполнил поиск в google с 18014398509481984 - 18014398509482000 как поисковый запрос, и он вернул результат 0, что означает, что оба они одинаковы.

Вопросы

1 - Если оба одинаковы, почему второе значение выглядит иначе? Я могу видеть 1984 в 2000.

2 - Почему происходит преобразование?

3 - Как избежать этого типа преобразований?

Любая помощь будет замечательной!

  • 1
    Какой тип столбца в первой таблице? А во второй таблице? Похоже, что происходит преобразование из большого целого (64 бита) в двойное, теряя точность в операции, даже без какой-либо обработки.
  • 1
    RE: поиск в Google. LMFAO: D
Показать ещё 5 комментариев
Теги:
math
double
rounding

4 ответа

5
Лучший ответ

Попробуйте использовать System.Decimal для сохранения значения из первой таблицы вместо System.Double. System.Double, похоже, не содержит достаточно значимых цифр, чтобы точно хранить это значение.

  • 0
    Благодарю. Я попробую с десятичным типом.
3

Значение двойной точности является точной только для 15 или 16 десятичных цифр (см. здесь для объяснения). Если вам нужно сохранить больше, чем это, вам придется использовать другой формат номера. Если вы хотите работать с очень большими целыми числами без потери точности, тогда есть различные классы, которые помогут вам этот.

Если вы получаете значение из SQL, убедитесь, что ваш целевой тип данных в .NET соответствует - SQL bigint для С# long, например, чтобы избежать проблем округления, подобных этому.

  • 0
    Мой тип таблицы NUMBER, и я использую базу данных Oracle
2

Я считаю, что это связано с точностью с плавающей запятой (большое число будет использовать мантисса экспонента), что означает, что он будет по существу представлен как фракционное число с мощностью. Однако дробные числа сталкиваются с ошибками округления из-за арифметики с плавающей запятой.

Обычно, чтобы избежать значений с плавающей запятой (попробуйте Int64), используйте более точный тип (десятичный) или учетную запись для ошибки и сделайте "приблизительно равным".

  • 0
    Благодарю. Что вы подразумеваете под «примерно равно»?
  • 0
    Вы можете добавить метод расширения в Double или статический метод, который определяет, будут ли значения, скажем, 0,001% друг в друге, и если это так, предположите, что они равны. Очевидно, вы установили порог в точке, с которой вы счастливы.
2

Нужно ли хранить их как числа с плавающей запятой?

Если нет, вы можете вместо этого использовать 64-битные целые числа: BIGINT в базе данных и long/Int64 в вашем приложении.

Они имеют диапазон от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807 и не имеют проблем с точностью и точностью.

  • 0
    Благодарю. Но моим значением будет число с плавающей запятой. Так что я думаю int64 или long не подойдет.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню