浮点值的范围分析?

时间:2014-04-18 13:00:27

标签: c++ c image-processing floating-point fixed-point

我有一个使用浮点计算的图像处理程序。但是,我需要将其移植到没有浮点支持的处理器中。所以,我必须改变程序以使用定点计算。为此我需要适当缩放那些浮点数,我需要知道所有值的范围,包括浮点计算的中间值。

有没有一种方法可以运行程序,它会自动给出程序中所有浮点计算的范围?试图手动弄清楚范围会太麻烦,所以如果有一些工具可以做到这一点,那就太棒了!

3 个答案:

答案 0 :(得分:3)

您可以使用一些"测量"根据这些行(live example)替换您的浮动类型:

template<typename T>
class foo
{
    T val;

    using lim = std::numeric_limits<int>;

    static int& min_val() { static int e = lim::max(); return e; }
    static int& max_val() { static int e = lim::min(); return e; }

    static void sync_min(T e) { if (e < min_val()) min_val() = int(e); }
    static void sync_max(T e) { if (e > max_val()) max_val() = int(e); }

    static void sync(T v)
    {
        v = std::abs(v);
        T e = v == 0 ? T(1) : std::log10(v);
        sync_min(std::floor(e)); sync_max(std::ceil(e));
    }

public:
    foo(T v = T()) : val(v) { sync(v); }
    foo& operator=(T v) { val = v; sync(v); return *this; }

    template<typename U> foo(U v) : foo(T(v)) {}
    template<typename U> foo& operator=(U v) { return *this = T(v); }

    operator T&() { return val; }
    operator const T&() const { return val; }

    static int min() { return min_val(); }
    static int max() { return max_val(); }
};

一样使用
int main ()
{
    using F = foo<float>;
    F x;

    for (F e = -10.2; e <= 30.4; e += .2)
        x = std::pow(10, e);

    std::cout << F::min() << " " << F::max() << std::endl;  // -11 31
}

这意味着您需要为浮动类型(Floatfloat)定义别名(例如double)并在整个程序中一致地使用它。这可能不方便,但最终可能证明是有益的(因为那时你的程序更通用)。如果您的代码已经在浮动类型上进行了模板化,那就更好了。

在此参数化之后,您可以将程序切换为&#34;测量&#34;或&#34;发布&#34;模式是将Float定义为foo<T>T,其中T是您的floatdouble

好消息是您不需要外部工具,您自己的代码会执行测量。不好的是,按照目前的设计,它不会捕获所有中间结果。您必须为此foo定义所有(例如算术)运算符。这可以做,但需要更多的工作。

答案 1 :(得分:3)

不能在不支持浮点的硬件上使用浮点代码 - 编译器将提供执行浮点运算的软件例程 - 它们可能相当慢 - 但如果它足够快你的应用,这是阻力最小的路径。

实现定点数据类型类并使其成员函数检测上/下溢作为调试选项可能是最简单的(因为检查会降低代码速度)。

我建议你看看Anthony Williams' fixed-Point math C++ library。它是在C ++中定义的fixed类具有广泛的函数和运算符重载,因此可以在很大程度上通过用float替换现有代码中的doublefixed来使用它。它使用int64_t作为基础整数数据类型,具有34个整数位和28个小数位(34Q28),因此适用于大约8位小数且比int32_t更宽的范围。

它没有我建议的欠/溢检查,但它是你添加自己的好起点。

在32位ARM上,这个库的执行速度比软件浮点快5倍,在性能上与ARM的VFP单元的C代码相当。

请注意,此库中的sqrt()函数对于非常小的值具有较差的精度性能,因为它在可以保留的中间计算中丢失了低阶位。可以通过将其替换为我在this question中提供的版本的代码来改进它。

答案 2 :(得分:2)

对于自包含的C程序,您可以使用Frama-C's value analysis获取浮点变量的范围,例如下面的h

value analysis on floating-point variable h

g计算变量h

value analysis on floating-point variable g

有一种规范语言可以描述输入的范围(没有这些信息,很难说任何信息)。在上面的示例中,我使用该语言来指定预期要执行的函数{<1}}:

float_interval

Frama-C最容易在Linux上安装,Debian和Ubuntu二进制包可用于最新版本(但通常不是最新版本)。

如果您可以发布您的代码,这将有助于说明这种方法是否切合实际。例如,如果您的代码是C ++(您的问题没有说明,它标记有多个语言标记),那么当前版本的Frama-C将无济于事,因为它只接受C程序。