我有以下代码:
int foo = SamplingSomeValue();
int threshold = foo * 7 / 10;
...这意味着,算法对一些值进行采样,并将采样值的70%设置为下界阈值,以找到那些相似的值。
然而,常量7/10是丑陋的。通过将其替换为tRatio,它更具可读性,其中tRatio被定义为constexpr float tRatio = 0.7;。然而,在没有浮点运算硬件单元的嵌入式处理器中,它的效率并不高。
很明显,我们不能写constexpr int tRatio = (7/10);,因为它是0。
保持效率和可读性的最好方法是什么?
发布于 2016-09-06 18:35:35
出于可读性和可维护性的考虑,可以定义一个包含以下内容的cFraction类
class cFraction
{
public:
cFraction( int num, int den ) : m_num(num), m_den(den){ }
int operator*( int rhs ) const
{
return (rhs * m_num) / m_den ;
}
private:
int m_num ;
int m_den ;
} ;和非成员重载:
int operator*( int lhs, const cFraction& rhs )
{
return rhs * lhs ; // Multiply is commutative,
// swap operands to use member overload
}然后给出:
const cFraction SEVENTY_PERCENT( 7, 10 ) ;你可以这样写:
int threshold = foo * SEVENTY_PERCENT ;或者:
int threshold = SEVENTY_PERCENT * foo ;当然,虽然这提供了可读性,但考虑到名称相当通用,您可能不得不使用一组完整的重载和类型转换来完成类,以使cFraction看起来像一个完整的算术类型。这在其他情况下可能确实有用,但您可能可以通过只实现上面的代码并将其命名为类似于cIntegerRatio的名称来避免这种情况,以清楚地表明该类具有非常特定的用途,并且只有乘以整数才有意义。
发布于 2016-09-06 19:31:48
这不是对你问题的直接回答,而是一个重要的考虑因素。
关于以下内容的声明
...没有浮点运算硬件单元的嵌入式处理器...
表示代码中的任何除法或模运算都编译为函数调用(该函数通常是随处理器软件开发工具包一起提供的库的一部分)。
如果您要多次执行此foo * 7 / 10操作,那么我建议您采取一些编码优化措施。
例如:foo * 11 / 16,编译器随后可以将其解释为foo * 11 >> 4。
选择的分子越高,获得更高准确率的机会就越高:
foo * 11 / 16foo * 22 / 32无改进来自previousfoo * 44 / 64无改进来自previousfoo * 89 / 128foo * 179 / 256foo * 358 / 512无改进来自previousfoo * 716 / 1024无改进来自previousfoo * 1443 / 2048foo * 2867 / 4096当然,缺点是乘法可能会溢出。
为了决定使用哪个因子,您需要考虑:
foo类型的大小foo在任何程序执行过程中可以保留的最大值发布于 2016-09-07 19:20:31
你能做的是,
#define FRAC 7/10
#define DIV(x) (x)*FRAC
...
int threshold = DIV(foo) 如果您确保只在DIV宏中使用FRAC,则可以省去FRAC定义中的括号(在本例中是一个例外),而在代码中使用DIV宏。
https://stackoverflow.com/questions/39340267
复制相似问题