【问题标题】:Define division by zero as infinity将除以零定义为无穷大
【发布时间】:2019-06-18 08:13:35
【问题描述】:

我想将除以零的结果定义为双 INF。

有一些关于 C/C++ 中除以零的默认行为的讨论。没有问题(我读过)明确地询问如何在 C 中定义除以零以成为无穷大。这是否有意义我宁愿不讨论。我只想为一个包含多个 C 函数的文件以这种方式定义它,并且需要它的语法。

【问题讨论】:

  • 表面上听起来不太可能,但这可能取决于您的控制水平。例如:你能用函数调用替换所有除法运算吗?简而言之-您尝试了什么? :)
  • 浮点除以零已经导致INF。如果你想用同样的方式定义整数,你必须打破标准,因为整数除法得到一个整数,它不能代表INF
  • 通过在除法之前捕获零除数可能更容易处理整数除法。另一种方法是建立恢复机制。
  • 如果代码试图避免 -1.0/0.0-INF?听起来你也希望它是 +INF

标签: c


【解决方案1】:

如果您需要这种行为,请使用可以表示无穷大的浮点数,并提供所需的行为。请注意,从技术上讲,这是未定义的行为,但实际上大多数编译器(所有标准架构的主流编译器)都实现了 IEEE 754 语义,例如GCC.

int main() {
    float f = 42;
    float g = f / 0.0f;
    printf("%f\n", g);
}

输出:

inf

这是可以依赖的行为,因为编译器清楚地记录了它。但是,在编写可移植代码时,请确保在代码中测试这些假设(例如,通过测试是否定义了预处理器宏 __STDC_IEC_559__as well as compiler-specific macros)。

如果出于某种原因,您需要整数值的这种行为,唯一的办法就是创建自己的类型。像这样的:

typedef struct {
    int value;
    bool is_inf;
    bool is_nan;
} ext_int;

ext_int make_ext_int(int i) {
    return (ext_int) {i, false, false};
}

ext_int make_nan() {
    return (ext_int) {0, false, true};
}

ext_int make_inf(int sign) {
    return (ext_int) {(sign > 0) - (sign < 0), true, false};
}

ext_int ext_div(ext_int a, ext_int b) {
    if (a.is_nan || b.is_nan) {
        return  make_nan();
    }
    if (b.value == 0) {
        return make_inf(a.value);
    }
    // TODO: insert other cases.
    return (ext_int) {a.value / b.value, false, false};
}

...在实际的实现中,您会打包不同的标志,而不是为每个标志分别设置 bool

【讨论】:

  • 浮点除以零仍然是标准未定义的行为,尽管 IEEE754 确实以正分子的方式定义它。
  • if (b.is_nan || b.is_inf) { return make_nan(); 看起来不对。你想要if (a.is_nan || b.is_nan) { ...吗?代码也需要更多案例。是 a=INT_MIN, b = -1 的 UB ...
  • @chux 这是一篇非常快速的文章,测试有限。目的是明确不是生产代码(这会太长),而是一个说明。也就是说,条件的目的是确保x / inf 返回NaN。你是对的,那是错误的。
  • 根据需要,不一定需要自己的新结构,只需要自定义函数即可。 INT_MININT_MAX比较少用;说“好吧,这些现在是无穷大”并不是没有道理的。
  • 出于好奇,您能想到 any 编译器,它的浮点值为无穷大,但不计算 1./0。作为无穷大?虽然它是正式的 UB,但似乎无穷大值的存在强烈暗示 1/0=inf。
【解决方案2】:

C 标准未定义浮点除以零。

(IEEE754 - 常见但绝不无处不在 - 如果a 为正,则定义a / 0.0+INF,如果a 为负,则-INFNaN 如果a 也是零) .

最好的办法是定义一个模拟除法运算符的函数,并在那里实现你的行为。

【讨论】:

    猜你喜欢
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2014-09-11
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    相关资源
    最近更新 更多