Работа с двойными неточностями, кроме использования десятичных дробей - PullRequest
2 голосов
/ 29 сентября 2010

У меня проблема с неточностью двойных чисел при использовании обычных математических операций.Это тот случай, когда простое дополнение добавит 00000000x к моему двойнику.

Я прочитал из другой вопрос , что вместо него следует использовать десятичные дроби.

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

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

1 Ответ

1 голос
/ 30 октября 2010

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

Например, используйте следующее для 4 десятичных знаков:

double d = ___;
string s = String.Format(
    System.Globalization.CultureInfo.InvariantCulture,
    "{0:0.0000}", d);
Console.WriteLine(s);

Имейте в виду, что это не означает, что вы получите тот же результат, как если бы вы делали это с карандашом и бумагой, или с ручным калькулятором, или с математической точностью с неограниченной точностью. Это также не означает, что отображаемый результат является правильным +/- 0,00005 (для приведенного выше примера): при промежуточных вычислениях могут быть накоплены ошибки аппроксимации.

Ниже показано, как сделать что-то похожее с научной нотацией:

string s = String.Format(System.Globalization.CultureInfo.InvariantCulture,
    "{0:0.0000E0}", d);

См. http://msdn.microsoft.com/en-us/library/0c899ak8.aspx для получения дополнительной информации о пользовательских строках числового формата.

Если вас не интересует фактическое отображение или сохранение значения в виде строки, другой вариант - преобразовать в Decimal и округлить после выполнения критических для производительности вычислений в double:

Decimal dec = Decimal.Round((Decimal)d, 4);

Обратите внимание, что когда требуется точное соответствие карандашным и бумажным методам, вы должны использовать Decimal для всех этапов расчета, так как нет преобразований из базы в 10 в базу 2 и соответствующая ошибка аппроксимации, связанная с такие базовые преобразования. При этом, Decimal - это не безграничная точность: есть еще способы встретить ошибки аппроксимации, хотя для наиболее распространенных случаев использования (например, для многих видов финансовых расчетов) Decimal будет «просто работать».

...