我正在尝试实现一个带舍入的整数除法。显然,默认情况下整数除法是取整的,我想我可以用余数来决定我是否应该在结果上加1。在此解决方案中,处理器周期非常宝贵(以10 kHz运行),因此我正在寻找以最小开销实现此目的的方法,或者理想情况下,作为现有除法计算的一部分“免费”获得结果我的问题是,有人知道在G0上实现这个的好方法吗,它实际上没有除法指令,我需要进入反汇编程序,看看它在做什么吗,我需要自己写汇编代码吗,有什么公认的解决方案吗?注:商和除数都是任意数,不是常数。
nnsrf1az1#
我的问题是,有人知道在G0上实现这一点的好方法吗?G0实际上没有除法指令。我不知道有什么通用方法比编译器已经做的更快。在以下情况下,有一些方法可以比通用代码更快:
INT_MIN/-1
设q = rounded_division(a, b)
q = rounded_division(a, b)
使用div(),它在一次操作中计算a/b和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
在除之前,将除数加一半(带选择符号)。
// 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)。
1条答案
按热度按时间nnsrf1az1#
我的问题是,有人知道在G0上实现这一点的好方法吗?G0实际上没有除法指令。
我不知道有什么通用方法比编译器已经做的更快。
在以下情况下,有一些方法可以比通用代码更快:
INT_MIN/-1
设
q = rounded_division(a, b)
使用
div()
,它在一次操作中计算a/b
和a%b
。a >= 0
、b > 0
和a + b/2
未溢出时:除前将除数的一半相加。
a + b/2
(a - b/2
)未溢出时:在除之前,将除数加一半(带选择符号)。
这里的四舍五入是"四舍五入到最接近的,远离0的关系"。
一些潜在的优化可能与符号比较,但往往难以理解。通常情况下,编译将发出良好的代码没有这样的精心编制的代码。例如:
除以0和
INT_MIN/-1
仍然是 * 未定义的行为 *(UB)。