Cortex M0+/GCC刻度(带舍入)

wz1wpwve  于 2023-02-11  发布在  其他
关注(0)|答案(1)|浏览(121)

我正在尝试实现一个带舍入的整数除法。显然,默认情况下整数除法是取整的,我想我可以用余数来决定我是否应该在结果上加1。
在此解决方案中,处理器周期非常宝贵(以10 kHz运行),因此我正在寻找以最小开销实现此目的的方法,或者理想情况下,作为现有除法计算的一部分“免费”获得结果
我的问题是,有人知道在G0上实现这个的好方法吗,它实际上没有除法指令,我需要进入反汇编程序,看看它在做什么吗,我需要自己写汇编代码吗,有什么公认的解决方案吗?
注:商和除数都是任意数,不是常数。

nnsrf1az

nnsrf1az1#

我的问题是,有人知道在G0上实现这一点的好方法吗?G0实际上没有除法指令。
我不知道有什么通用方法比编译器已经做的更快。
在以下情况下,有一些方法可以比通用代码更快:

  • 分子(被除数)的范围为非负数。
  • 分母(除数)的范围为正数。
  • 我们可以忽略INT_MIN/-1
  • 取整模式连接远离0(如下所示),而不是连接到偶数。

q = rounded_division(a, b)

  • 一般用途:

使用div(),它在一次操作中计算a/ba%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 >= 0b > 0a + b/2未溢出时:

除前将除数的一半相加。

q = (a + b/2)/b;
  • a + b/2a - 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)。

  • (我希望我把所有的案例都编码正确。有点晚了。所以以后再复习。)*

相关问题