将错误代码返回为double

时间:2015-03-17 20:44:12

标签: c++ c comparison point floating

我想知道是否可以在C中以下列方式将错误代码返回为double:

double getValue()
{
    double ret = 0;

    if (error1)
    {
        return -1;
    }
    if (error2)
    {
        return -2;
    }
    return ret = ....;
}

int main(void)
{
    double val = getValue();

    if (-1 == val)
    {
        printf("getValue: error1\n")
        return -1;
    }
    else if (-2 == val)
    {
        printf("getValue: error2\n");
        return -2;
    }

    ......
    return 0;
}

所以当返回值>> = 0时,它是正确的值,可以用于计算。当值小于零时发生错误。 当我将返回值与-1或-2进行比较时,我会得到浮点比较问题吗?

4 个答案:

答案 0 :(得分:3)

标志值是一个坏主意。浮点的标志值是双倍的,即使是双精度。

如果您使用的是IEEE双精度浮点值,则值-1-2可以完全表示为double,并且可以很好地定义比较。如果您仅复制double或仅读取该值,则不会出现“魔术错误”。实际上,在具有常规2s补充32位int s的系统上,每个int可以完全表示为IEEE双精度浮点值。

现在,您认为无关紧要的转换会像x /3. * 3.一样破坏身份,因此代码非常脆弱:脆弱,因为标志值很脆弱,并且因为浮点等价在实践中往往是脆弱的。

在C ++中,有很多方法可以做到这一点,不那么脆弱。

enum error_code {a,b,c};
boost::variant<double, error_code> getValue();

是一个标记的联合,可以包含doubleerror_code。您可以查看一个std::expected提案,该提案是一个带有“偏见”的标记联盟,第一个值是唯一有效的一个(std::experimental::optionalboost::variant之间的交叉排序)

这两个都导致以类型安全的方式返回值,其中错误是值的类型与非错误返回类型不同。

替代解决方案包括单独返回错误代码(作为返回值,或将指针指向错误代码作为参数(我称之为ICU样式))。在这种情况下,double可以设置为无关紧要的值(例如NaN)而不是未初始化。

double getValue( error_code* e );

error_code getValue( double* out );

其中enum error_code { a = -1, b = -2 }是错误代码的枚举。

答案 1 :(得分:2)

@LightnessRacesinOrbit击败了我,但打了它之后我还是发布了它。

您可以通过将值设置为指针参数并返回状态来完成此操作。这样,就不会禁止*ret的值。

int getValue(double *ret)
{
    *ret = ...;

    if (error1)
        return -1;
    if (error2)
        return -2;

    return 0;
}

然后调用代码可以是

double myval;
int err;
if ((err = getValue(&myval)) == 0)
    printf ("getValue() returned %f\n", myval);
else
    printf ("getValue() returned error %d\n", err);

答案 2 :(得分:1)

是的,你可能会遇到浮点错误。

因此,请考虑使用异常,或者返回int错误代码并填充double&#34;输出参数&#34;成功:

int getValue(double& ret)
{
    if (error1)
        return -1;
    if (error2)
        return -2;

    ret = ....;
    return 0;
}

答案 3 :(得分:0)

这样做并不是必需的,并且难以处理错误,您应该创建一个enum,您可以根据需要添加或删除错误代码,而且您实际上并不需要记住-1是{或-2是什么意思,只是给每个错误一个描述性名称,然后执行此操作

enum ErrorCodes {NoError, Error1, Error2, ... , ErrorN};
enum ErrorCodes getValue(double *value)
 {
    if (error1)
        return Error1;
    if (error2)
        return Error2;
    .
    .
    .
    if (errorN)
        return ErrorN;
    *value = resultOfCalculation;

    return NoError;
 }

然后

enum ErrorCode code;
double         value;

code = getValue(&value);
switch (code)
 {
    case NoError:
        /* use value here */
        break;
    case Error1:
        /* handle error 1 */
        break;
    /* and so on */
 }

我认为这样做更好,更优雅,因为无论目标值是什么类型,您都可以随时应用它,无论目标值是什么类型,这对于structdoubleint数组。