我正在写一个数独求解器,我必须计算我学到的东西被称为int
到0
的汉明距离,例如7
(二进制为111
)到0
的汉明距离为3
。所以我只是这样做:
for(int dist = 0 ; num != 0 ; num>>=1) dist += (num&1);
虽然效果很好,但我发现它有点笨拙。我试图想出一个二元操作技巧来计算距离(主要是为了好玩),但我只能找到适用于距离1
的方法:
(num-1) ^ ((num<<1)-1) == num → true only if hamming dist to 0 == 1
我查看了StackOverflow和网络,但我找不到任何东西。
假设num
永远不为负且始终小于512
,是否有更好/更优雅的方式来评估它,也许是一些二元操作技巧?如果没有,根据上面的假设,汉明距离的近似值是否始终在误差< 1
内?
答案 0 :(得分:2)
要创建9位的查找表(因为这是针对Sudoku):
int dist[512];
dist[0] = 0;
for (i=1; i<512; i++)
dist[i] = (i&1) + dist[i/2];
为了避免初始计算,这也可以写为记忆递归函数。
int dist(int bits) {
static _dist[512] = {};
if (bits == 0)
return 0;
else if (_dist[bits] == 0)
_dist[bits] = (bits & 1) + dist(bits/2);
return _dist[bits];
答案 1 :(得分:1)
在java中,您可以使用静态方法Integer.bitCount(int i)
如果你需要用另一种语言,这就是java源码,它应该是非常好的翻译。
select row_number()over(order by dt) as id
,dt as created_at
,cnt1+cnt2+cnt3+cnt4+cnt5 as cnt
from
(
select
date_table.dt
,lag(cnt,2,0)over(order by created_at asc) as cnt1
,lag(cnt,1,0)over(order by created_at asc) as cnt2
,isnull(cnt,0) cnt3
,lead(cnt,1,0)over(order by created_at asc) as cnt4
,lead(cnt,2,0)over(order by created_at asc) as cnt5
from
date_table left join
(select created_at,count(*) as cnt from your_table group by created_at) c
on date_table.day = c.created_at
) T
答案 2 :(得分:0)
不确定,如果这有帮助,但出于好奇我通过模板实现了它:
template <int N>
struct Hamming {
enum { value = Hamming< (N/2) >::value + (N&1)};
};
template <>
struct Hamming<0>
{
enum { value = 0 };
};
int main() {
std::cout << Hamming<7>::value << std::endl;
return 0;
}
只有在编译时知道N才能使用它,因此我认为你必须在你的情况下使用其他东西。但是,它很好地演示了如何(原则上)完全避免运行时的任何计算。