我想知道是否可以在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进行比较时,我会得到浮点比较问题吗?
答案 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();
是一个标记的联合,可以包含double
或error_code
。您可以查看一个std::expected
提案,该提案是一个带有“偏见”的标记联盟,第一个值是唯一有效的一个(std::experimental::optional
和boost::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 */
}
我认为这样做更好,更优雅,因为无论目标值是什么类型,您都可以随时应用它,无论目标值是什么类型,这对于struct
或double
或int
数组。