【问题标题】:Avoiding OverflowException when converting from double to decimal从双精度转换为十进制时避免溢出异常
【发布时间】:2016-11-04 09:20:53
【问题描述】:

double(或float)转换为decimal 时,可能会出现溢出异常。所以我写了这个小扩展方法,通过饱和来防止这种情况:

public static decimal ToDecimalSafe(this double input)
{
    try
    {
        return (decimal)input;
    }
    catch (OverflowException)
    {
        if (input < 0)
            return decimal.MinValue;
        else
            return decimal.MaxValue;
    }
}

问题是,这种溢出在我的用例中经常发生,违反了“例外应该是例外”的准则。是的,这会减慢应用程序的速度,但这并不是非常重要。真正的问题是它还会在调试过程中导致许多第一次机会异常,这很烦人。这是第二次尝试,似乎工作正常:

public static decimal ToDecimalSafe(this double input)
{
    if (input < (double)decimal.MinValue)
        return decimal.MinValue;
    if (input > (double)decimal.MaxValue)
        return decimal.MaxValue;

    try
    {
        return (decimal)input;
    }
    catch (OverflowException)
    {
        if (input < 0)
            return decimal.MinValue;
        else
            return decimal.MaxValue;
    }
}

我离开了 try-catch 以确保我捕捉到一些可能的边缘情况。这里的问题是:是否有任何极端情况或者我可以省略 try-catch 吗?

double 可以是 &gt;= (double)decimal.MinValue&lt;= (double)decimal.MaxValue 并且在转换时仍然会导致溢出吗?

【问题讨论】:

  • 如果这种情况经常发生,你到底为什么要使用decimal 而不是double?听起来您使用 decimal 进行工程或科学计算而不是财务计算 - 这是不正确的做法。
  • @MatthewWatson 这不是高精度或任何东西。它只是用于在一些处理双精度和用户提供并使用十进制的设置的硬件之间进行交互。硬件提供了限制,通常范围非常大,用户无论如何都不关心。
  • @MatthewWatson “相当频繁”并不意味着每秒 1000 次,它意味着在抓住这些设置限制时总共 100 次。
  • 听起来还是有人在某处使用decimal 获取科学或工程数据,这是错误的。将 decimal 用于从硬件发送/检索的数字尤其糟糕,这肯定不会理解 .Net decimal 结构 - 但可能会对 IEEE 标准的 double 类型感到满意。跨度>
  • @MatthewWatson 它被用于机器参数,它们不需要太多的精度,并且通常固定在几个小数位置。在这种情况下,十进制对其表示属性很方便。 NumericUpDown 控件也很方便,它们不理解双精度数。当然,参数在发送到硬件之前会转换为双精度。

标签: c# exception floating-point overflowexception


【解决方案1】:

该异常将不再发生。您可以通过这种方式修改您的代码。

public static decimal ToDecimalSafe(this double input)
{
    if (input < (double)decimal.MinValue)
        return decimal.MinValue;
    else if (input > (double)decimal.MaxValue)
        return decimal.MaxValue;
    else
        return (decimal)input;
}

你也可以使用特定的convert方法但它不会阻止异常

Convert.ToDecimal

如果您的问题只是令人讨厌的调试中断,那么我建议您查看 [DebuggerStepThrough] 或 [DebuggerHidden] 属性

【讨论】:

  • 我不知道这些属性,谢谢。很有用。顺便说一句,我实际上只花了几分钟时间试图自己解决这个问题,似乎给 (double)decimal.MinValue 或 (double)decimal.MaxValue 作为输入引发了异常。进行包含性比较(=)可以解决问题,但我必须弄清楚如何找到一个稍微在界限内的值,看看是否会崩溃。
  • 您还需要处理 double.NaN 值
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多