我有一个使用浮点计算的图像处理程序。但是,我需要将其移植到没有浮点支持的处理器中。所以,我必须改变程序以使用定点计算。为此我需要适当缩放那些浮点数,我需要知道所有值的范围,包括浮点计算的中间值。
有没有一种方法可以运行程序,它会自动给出程序中所有浮点计算的范围?试图手动弄清楚范围会太麻烦,所以如果有一些工具可以做到这一点,那就太棒了!
答案 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
}
这意味着您需要为浮动类型(Float
或float
)定义别名(例如double
)并在整个程序中一致地使用它。这可能不方便,但最终可能证明是有益的(因为那时你的程序更通用)。如果您的代码已经在浮动类型上进行了模板化,那就更好了。
在此参数化之后,您可以将程序切换为&#34;测量&#34;或&#34;发布&#34;模式是将Float
定义为foo<T>
或T
,其中T
是您的float
或double
。
好消息是您不需要外部工具,您自己的代码会执行测量。不好的是,按照目前的设计,它不会捕获所有中间结果。您必须为此foo
定义所有(例如算术)运算符。这可以做,但需要更多的工作。
答案 1 :(得分:3)
不能在不支持浮点的硬件上使用浮点代码 - 编译器将提供执行浮点运算的软件例程 - 它们可能相当慢 - 但如果它足够快你的应用,这是阻力最小的路径。
实现定点数据类型类并使其成员函数检测上/下溢作为调试选项可能是最简单的(因为检查会降低代码速度)。
我建议你看看Anthony Williams' fixed-Point math C++ library。它是在C ++中定义的fixed
类具有广泛的函数和运算符重载,因此可以在很大程度上通过用float
替换现有代码中的double
或fixed
来使用它。它使用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
:
从g
计算变量h
:
有一种规范语言可以描述输入的范围(没有这些信息,很难说任何信息)。在上面的示例中,我使用该语言来指定预期要执行的函数{<1}}:
float_interval
Frama-C最容易在Linux上安装,Debian和Ubuntu二进制包可用于最新版本(但通常不是最新版本)。
如果您可以发布您的代码,这将有助于说明这种方法是否切合实际。例如,如果您的代码是C ++(您的问题没有说明,它标记有多个语言标记),那么当前版本的Frama-C将无济于事,因为它只接受C程序。