Безопасное автоматическое приведение от двойного к десятичному: безопасно ли следующее? - PullRequest
5 голосов
/ 27 июля 2011

Безопасно ли приводить от двойного к десятичному в C # следующим образом:

int downtimeMinutes = 90;
TimeSpan duration = TimeSpan.FromHours(2d);
decimal calculatedDowntimePercent = duration.TotalMinutes > 0?
    (downtimeMinutes / (decimal)duration.TotalMinutes) * 100.0m : 0.0m;

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

Ответы [ 3 ]

3 голосов
/ 27 июля 2011

Как правило, double -> decimal преобразования не являются безопасными, поскольку decimal имеет меньший диапазон.

Однако, если TotalMinutes меньше максимального decimal значение * это будет хорошо.Это верно, потому что TimeSpan.MaxValue.TotalMinutes < (double)decimal.MaxValue (я полагаю, TimeSpan использует long для внутреннего использования.)

Итак: да.

*: (79 228 162 514 644 337 593 543 950 335 минут в 1,1 × 10 ^ 13 развозраст вселенной)

2 голосов
/ 27 июля 2011

Да, это безопасно, потому что десятичная дробь имеет большую точность

http://msdn.microsoft.com/en-us/library/364x0z75(VS.80).aspx

Компилятор помещает приведенные числа вокруг других не десятичных чисел, но все они помещаются в десятичные числа * (см. Предостережение).

- Протест

  • Десятичное число не является типом с плавающей запятой. Его задача - всегда поддерживать точность. Принимая во внимание, что число с плавающей запятой, такое как double (которое я в основном использую), компенсирует точность для размещения очень больших чисел). Очень большие или очень маленькие числа не будут вписываться в десятичную. Поэтому Лизе нужно спросить себя, будет ли масштаб операции меньше 28 значащих цифровых цифр. 28 значащих цифр подходят для большинства сценариев.

  • Плавающая точка хороша для астрономически больших или бесконечно малых чисел ... или операций между ними, которые дают достаточную точность. Я должен поискать это, но двойное это хорошо для плюс или минус несколько миллиардов с точностью до нескольких десятичных знаков (до 7 или 8?).

  • в науках нет смысла измерять сверх точности вашего оборудования. В финансах часто логический выбор является двойным, потому что двойное вычисление более эффективно в вычислительном отношении для большинства ситуаций (иногда они хотят немного большей точности, но эффективность не стоит отбрасывать для чего-то вроде десятичного). В конце концов, мы все должны выработать прагматичные и сопоставить потребности бизнеса с цифровой областью. Существуют инструменты с динамическим представлением чисел. Вероятно, есть библиотеки в .net для того же самого. Однако стоит ли это того? Иногда это так. Часто это излишне.

1 голос
/ 29 декабря 2016

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

[TestCase(double.MinValue)]
[TestCase(double.MaxValue)]
[TestCase(double.NaN)]
[TestCase(double.NegativeInfinity)]
[TestCase(double.PositiveInfinity)]
public void WillFail(double input)
{
    decimal result = (decimal)input; // Throws OverflowException!
}

Как указано в ОП,комментарий к вопросу, что « safe » означает «, не вызывает исключений времени выполнения », приведенное выше показывает, что исключения могут возникнуть при приведении двойного числа кдесятичный.


Выше приведен общий ответ, к которому многие гуглеры могли бы прийти сюда.Тем не менее, чтобы ответить на вопрос * , заданный OP, есть убедительный признак того, что код не будет генерировать исключения, даже в крайних случаях:

[Test]
public void SpecificCodeFromOP_WillNotFail_NotEvenOnEdgeCases()
{
    int downtimeMinutes = 90;
    foreach (TimeSpan duration in new[] {
        TimeSpan.FromHours(2d), // From OP
        TimeSpan.MinValue,
        TimeSpan.Zero,
        TimeSpan.MaxValue })
    {
        decimal calculatedDowntimePercent = duration.TotalMinutes > 0 ?
            (downtimeMinutes / (decimal)duration.TotalMinutes) * 100.0m : 0.0m;
    }
}
...