2个整型常量除法的c++嵌入式平台可读性

C++ embbeded platform readability for division of 2 integer constants

本文关键字:嵌入式 平台 可读性 c++ 整型常量 除法 2个      更新时间:2023-10-16

我有以下代码:

int foo = SamplingSomeValue();
int threshold = foo * 7 / 10;
...

,表示算法对某个值进行采样,并将采样值的70%作为下限阈值,寻找相似的值。

然而,常数7/10是丑陋的。用tRatio替换它更容易读,其中tRatio被定义为constexpr float tRatio = 0.7;。然而,在没有浮点运算硬件单元的嵌入式处理器中,它的效率不高。

显然我们不能写constexpr int tRatio = (7/10);,因为它是0。

保持效率和可读性的最好方法是什么?

为了可读性和可维护性,您可以定义一个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之类的东西,以明确该类具有非常特定的目的,并且只有乘以整数才有意义。

这不是对你问题的直接回答,而是一个重要的考虑。

关于 的语句

[…无浮点运算硬件单元的嵌入式处理器[…]

表示代码中的任何除法或取模操作都被编译为函数调用(该函数通常是与处理器软件开发工具包一起提供的库的一部分)。

如果您要多次执行此foo * 7 / 10操作,那么我建议您进行一些编码优化测量。

例如:foo * 11 / 16,编译器可以将其解释为foo * 11 >> 4

你选择的分子越高,越有可能得到更好的准确度:

  • foo * 11 / 16
  • foo * 22 / 32与上一个
  • 相比无改善
  • foo * 44 / 64与上一个
  • 相比没有改进
  • foo * 89 / 128
  • foo * 179 / 256
  • foo * 358 / 512与上一个
  • 相比无改善
  • foo * 716 / 1024与上一个
  • 相比没有改进
  • foo * 1443 / 2048
  • foo * 2867 / 4096

当然,缺点是乘法可能溢出。

为了决定使用哪个因素,您需要考虑:

  • 您的平台上foo类型的大小(sizeof *foo)
  • foo在任何程序执行期间可以保留的最大值

你能做的是,

#define FRAC 7/10
#define DIV(x) (x)*FRAC
...
int  threshold = DIV(foo) 

如果您确保FRAC仅在DIV宏中使用,那么您可以省略FRAC定义中的括号(在这种情况下作为例外),并在代码中使用DIV宏。