我正在尝试将整数四舍五入为数字的最接近倍数。
说数字等于80
。
是否有比x -= (x % the_number)
更有效的方法?
这是一个例子:
#include <stdio.h>
int main(void)
{
int x = 191;
int the_number = 80;
printf("x == %d\n", x);
x -= (x % the_number);
printf("x - (x %% the_number) == %d\n", x);
return 0;
}
这是另一个例子。它不是一个像以前的那样可以完全正常工作的程序,但是我想做的更清楚:
#define LIGHT_GRAY 0x0700
#define COLUMNS 80
void pm_putchar(int c, void **ptr)
{
c &= 0xff;
c |= LIGHT_GRAY;
if(c == '\n' | LIGHT_GRAY)
*ptr += COLUMNS;
else if(c == '\r' | LIGHT_GRAY)
*ptr -= (*ptr % COLUMNS);
**(short **)ptr = (short)c;
(*ptr) += 2;
}
在上面的示例中,假设*ptr
等于或高于VGA文本缓冲区(0x0b8000
)的位置。
答案 0 :(得分:3)
好吧,如果您仅尝试使用整数除数(您要除以的数字),总会有storeData
,但是这是否更好取决于您。但是,我不知道有什么更好的方法,但是您也许可以重新定位this thread上的某些答案。
答案 1 :(得分:3)
我正在尝试将整数四舍五入为数字的最接近倍数。 [...] 是否有比
x -= (x % the_number)
更有效的方法?
在一般情况下,不会。有效率相似的替代方案,例如
x = (x / the_number) * the_number
,但是您不会用少于两个算术运算来做到这一点。 (在某些体系结构上,-
的效率也比*
高,并且/
和%
的效率通常差不多)。
但是,如果您要截断到2的先进进阶幂,则可以通过使用单个按位&
来掩盖低阶位来做到这一点。例如,要截断到最接近的16的较低倍数(== 0x10),您可以编写
x &= ~0xf; // truncate an int x to a multiple of 16
答案 2 :(得分:2)
只有一种检查方法:
int r1(int r, const int n)
{
return r -= (r % n);
}
int r2(int r, const int n)
{
return (r / n) * n;
}
和生成的代码
r1:
mov eax, edi
cdq
idiv esi
mov eax, edi
sub eax, edx
ret
r2:
mov eax, edi
cdq
idiv esi
imul eax, esi
ret
div / mul方法的指令较少,但考虑到延迟和执行时间,imul可能会更慢。
答案 3 :(得分:0)
如果您怀疑该值可能是2的幂,则检查单个除数并使用移位和掩码处理mod是值得的。少数比特的收益递减,但可能值得。
if (!(b & (b-1))) {
x = a & (b-1);
} else {
x = a % b;
}
我对CPU不能简化这种简单情况感到惊讶,它在随机的64位mod上似乎是4-5倍。