Cortex M0+/GCC 舍入除法

问题描述 投票:0回答:1

我正在尝试实现带有舍入的整数除法。显然,默认情况下整数除法会取整,我想我可以使用余数来确定是否应该在结果中加 1。

在此解决方案中,处理器周期非常宝贵(以 10 kHz 运行),因此我正在寻找以最小开销实现此目的的方法,或者理想情况下“免费”获得结果作为现有除法计算的一部分

我的问题是,有谁知道在实际上没有除法指令的 G0 上实现这一点的好方法吗?我需要进行反汇编并看看它在做什么吗?我需要编写自己的汇编代码吗?有公认的解决方案吗?

注意:商和除数都是任意的,而不是常整数。

c gcc rounding cortex-m integer-division
1个回答
2
投票

我的问题是,有谁知道在实际上没有除法指令的 G0 上实现此目的的好方法吗?

我不知道有什么通用方法比编译器已经做的更快。

有一些方法可以比通用代码更快,如果:

  • 分子(被除数)的范围是非负数。

  • 分母(除数)的范围为正。

  • 我们可以忽略

    INT_MIN/-1

  • 舍入模式关系远离 0(如下所示),而不是关系到偶数。


q = rounded_division(a, b)

  • 通用:

使用

div()
在一次操作中计算
a/b
a%b

#include <stdlib.h>

div_t qr = div(a, b);
if (qr.quot >= 0) {
  if (a >= 0) { 
    if (b/2 > r.rem) qr.quot++;
  } else {
    if (b/2 < r.rem) qr.quot--;
  }  
} else {
  if (a >= 0) { 
    if (b/2 < r.rem) qr.quot--;
  } else {
    if (b/2 > r.rem) qr.quot++;
  }  
}
  • a >= 0
    b > 0
    a + b/2
    不溢出时:

除法前先加上除数的一半。

q = (a + b/2)/b;
  • a + b/2
    a - b/2
    )不溢出时:

除法之前将一半(带有选择符号)加到除数上。

  // If a and b have the same sign ...
  if ((a < 0) == (b < 0)) {
    q = (a + b/2)/b;
  } else { 
    q = (a - b/2)/b;
  }

此处进行的舍入是“舍入到最接近的,远离 0”。

通过符号比较可以实现一些潜在的优化,但通常更难理解。通常,即使没有这样精心设计的代码,编译也会生成良好的代码。 示例:

  // if ((a < 0) == (b < 0)) {
  if (!((a ^ b) & INT_MIN)) {

除以 0 和

INT_MIN/-1
仍然是 未定义行为 (UB)。


(我希望我对所有案例的编码都是正确的。)

© www.soinside.com 2019 - 2024. All rights reserved.