Math 如何在不使用任何算术运算的情况下找到x mod 15?

Math 如何在不使用任何算术运算的情况下找到x mod 15?,math,bit-manipulation,Math,Bit Manipulation,假设给我们一个无符号整数。在不使用任何算术运算符的情况下,即+-/*或%,我们可以找到x mod 15。我们可以使用二进制位操作 就我所能做到的而言,我是基于2分得出这个结论的 a=a mod 15=a mod 16用于a>4 所以a=(x&OxF+(x>>4)&OxF)&OxF 它归结为添加2个4位数字。这可以通过位表达式来完成 sum[0]=a[0]^b[0] sum[1]=a[1]^b[1]^(a[0]&b[0]) 。。。 等等 这对我来说似乎是欺骗。我希望有一个更优雅的解决方案你的逻辑有

假设给我们一个无符号整数。在不使用任何算术运算符的情况下,即
+
-
/
*
%
,我们可以找到
x mod 15
。我们可以使用二进制位操作

就我所能做到的而言,我是基于2分得出这个结论的

a=a mod 15=a mod 16
用于
a>4

所以
a=(x&OxF+(x>>4)&OxF)&OxF

它归结为添加2个4位数字。这可以通过位表达式来完成

sum[0]=a[0]^b[0]

sum[1]=a[1]^b[1]^(a[0]&b[0])

。。。 等等


这对我来说似乎是欺骗。我希望有一个更优雅的解决方案

你的逻辑有缺陷,但我一点也不怀疑。你自己想一想,你的最终公式在前8位上运行,而忽略了其余的。只有当您丢弃的部分(9+位)始终是15的乘积时,这才有效。然而,实际上(在二进制数中),9+位总是16的乘法,而不是15的乘法。例如,尝试在公式中输入1 0000 0000和11 0000 0000。对于这两种情况,您的公式都会给出0,而实际上答案是1和3

从本质上说,我几乎可以肯定,没有循环,你的任务是无法解决的。如果允许您使用循环,那么实现bitwiseAdd函数并使用它做任何您喜欢的事情都是最简单的

添加:

发现了你的问题。这是:

。。。a=x-15k(对于某些非负k)

。。。k基本上是x>>4


它等于x>>4,只是一些数字的巧合。举个大例子,比如x=11110000。根据你的计算,k=15,而实际上它是k=16:16*15=11110000。

这让我想起了10进制的一个老把戏,叫做“抛出9”。这用于检查手工执行的大额金额的结果。 在这种情况下,
123模9=1+2+3模9=6

这是因为9比数字(10)的基数小一。(证据省略;)

因此,考虑基数16(十六进制)中的数字。您应该能够做到:

0xABCE123 mod 0xF = (0xA + 0xB + 0xC + 0xD + 0xE + 0x1 + 0x2 + 0x3 ) mod 0xF 
                  = 0x42 mod 0xF 
                  = 0x6 
现在,您仍然需要使用一些魔法来使添加的内容消失。但它给出了正确的答案

更新:

<>是C++中的一个完整实现。
f
查找表将成对数字的和取为mod 15。(与mod 15字节相同)。然后,我们重新打包这些结果,并在每轮中重新应用一半的数据

#包括
uint8_t f[256]={
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,0,1,
2,3,4,5,6,7,8,9,10,11,12,13,14,0,1,2,
3,4,5,6,7,8,9,10,11,12,13,14,0,1,2,3,
4,5,6,7,8,9,10,11,12,13,14,0,1,2,3,4,
5,6,7,8,9,10,11,12,13,14,0,1,2,3,4,5,
6,7,8,9,10,11,12,13,14,0,1,2,3,4,5,6,
7,8,9,10,11,12,13,14,0,1,2,3,4,5,6,7,
8,9,10,11,12,13,14,0,1,2,3,4,5,6,7,8,
9,10,11,12,13,14,0,1,2,3,4,5,6,7,8,9,
10,11,12,13,14,0,1,2,3,4,5,6,7,8,9,10,
11,12,13,14,0,1,2,3,4,5,6,7,8,9,10,11,
12,13,14,0,1,2,3,4,5,6,7,8,9,10,11,12,
13,14,0,1,2,3,4,5,6,7,8,9,10,11,12,13,
14,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0};
uint64_t模块15(uint64_t in_v)
{
uint8_t*in=(uint8_t*)和in_v;
//12 34 56 78 12 34 56 78=>aa bb cc dd

in[0]=f[in[0]]|(f[in[1]]我看不出这有什么错,没有使用算术运算符,而是使用位运算符,这可能是他们想要的。这是家庭作业吗?如果是的话,应该标记为家庭作业。不是家庭作业。一位朋友向我提出了这个问题。你需要专门针对
mod 15
的解决方案还是针对任何模的通用解决方案?可能是帖子这是om math.SE或codegolf.SE以获得更优雅的解决方案?我不确定这是什么地方。为了消除添加的内容,您可以使用16x16查找表。:-@ShreevatsaR-确实,该算法看起来很粗糙,但可以简化为不太多的操作。因此,我添加了它的实现…(头部爆炸)好主意:25年后,DI在我十岁的时候独立发现了这一点,我仍然为此感到自豪。不幸的是,从那时起,这有点干燥。具体来说,k是x>>4当且仅当floor(x/15)=floor(x/16),当且仅当,x=15k+r,其中0≤R