如何绑定浮点算术结果?

发布于 2025-02-03 06:43:58 字数 420 浏览 1 评论 0原文

x = a/b之类的浮点操作通常不完全表示,因此CPU必须进行舍入。是否可以获得两个浮点x_lowx_up,它们分别比a/b的确切值少或等于最高的浮点。最低的浮点比a/b更高或平等?

某些条件是:

  • abx_lowx_upxfloat
  • ab是正面的,整数(1.0f2.0f , ETC)

Floating-point operations like x=a/b are usually not exactly representable so the CPU has to do rounding. Is it possible to get the two floats x_low and x_up that are respectively the highest floating point less or equals than the exact value of a/b and the lowest floating point higher or equals than a/b?

Some of the conditions are :

  • a, b, x_low, x_up and x are float
  • a and b are positive, integers (1.0f, 2.0f, etc)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

箜明 2025-02-10 06:43:58

这将为您提供可能太大的范围:

#include <cmath>
#include <utility>

template<typename T>
std::pair<T, T> bounds(int a, int b) {
    T ta = a, tb = b;
    T ta_prev = std::nexttoward(ta), ta_next = std::nextafter(ta);
    T tb_prev = std::nexttoward(tb), tb_next = std::nextafter(tb);
    return std::make_pair(ta_prev / tb_next, ta_next / tb_prev);
}

This will give you a bounds that might be too large:

#include <cmath>
#include <utility>

template<typename T>
std::pair<T, T> bounds(int a, int b) {
    T ta = a, tb = b;
    T ta_prev = std::nexttoward(ta), ta_next = std::nextafter(ta);
    T tb_prev = std::nexttoward(tb), tb_next = std::nextafter(tb);
    return std::make_pair(ta_prev / tb_next, ta_next / tb_prev);
}
热风软妹 2025-02-10 06:43:58

一种简单的方法是以更高的精度进行分区,并在转换为float时获得上/下限:

struct float_range {
    float lower;
    float upper;
};

float_range to_float_range(double d) {
    float as_float = static_cast<float>(d);
    double rounded = double{as_float};
    if (std::isnan(as_float) || rounded == d) {
        // No rounding done
        return { as_float, as_float };
    }
    if (rounded < d) {
        // rounded down
        return { as_float, std::nextafter(as_float, std::numeric_limits<float>::infinity()) };
    }
    // rounded up
    return { std::nextafter(as_float, -std::numeric_limits<float>::infinity()), as_float };
}

float_range precise_divide(float a, float b) {
    return to_float_range(double{a}/double{b});
}

An easy way to do it is to do the division in higher precision and get the upper/lower bound on conversion to float:

struct float_range {
    float lower;
    float upper;
};

float_range to_float_range(double d) {
    float as_float = static_cast<float>(d);
    double rounded = double{as_float};
    if (std::isnan(as_float) || rounded == d) {
        // No rounding done
        return { as_float, as_float };
    }
    if (rounded < d) {
        // rounded down
        return { as_float, std::nextafter(as_float, std::numeric_limits<float>::infinity()) };
    }
    // rounded up
    return { std::nextafter(as_float, -std::numeric_limits<float>::infinity()), as_float };
}

float_range precise_divide(float a, float b) {
    return to_float_range(double{a}/double{b});
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文