我在quote notation表示中为数字实现算术函数,这是p-adic numbers的一种形式。从this paper获取基本思想,我有一个结构和一个构造函数。
FlowRouter.redirect
这与论文大致相同,但我稍微改变了索引。
enum { base = 10 };
/*
d[n+m-1] ... d[n+1] d[n] ' d[n-1] ... d[2] d[1] d[0]
Sum(i=0..n d[i]*b^i) + Sum(i=n+1..n+m d[i]*b^i/(b^m-1))
*/
typedef struct q {
int b,n,m,d[];
} *q;
使用论文中提供的界限,我可以估计加法结果的数字。
/* nb. not defined for LONG_MIN */
q qlong(long i){
if (i<0) return qneg(qlong(-i));
int m=0;
int n=i?ceil(log(i)/log(base)):0;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
int j;
for(j=0; j<n; j++){
z->d[j] = i % base;
i /= base;
}
qprint(z);
return z;
}
但是一旦遇到重复状态,这可能会执行不必要的计算。在归一化步骤中进行更多计算。
在他的earlier paper中,Hehner提出了一种检测重复的算法。
q qadd(q x,q y){
int m=lcm(x->m,y->m);
int n=max(x->n,y->n)+m+2;
int t,c=0;
q z=malloc(sizeof*z + (n+m)*sizeof*z->d);
z->b=base; z->n=n; z->m=m;
int k;
for(k=0; k<n+m; k++){
t = qdig(x,k) + qdig(y,k) + c;
z->d[k] = t % base;
c = t / base;
}
findrepetition(z);
return z;
}
但是我可以将它合并到我现有的计算循环中而不是进行第二次传递吗?我在void findrepetition(q z){
int i;
int j;
qprint(z);
for(i=1; i<z->n+z->m-1; i*=2) {
for(j=i+1; j<2*i; j++) {
if (z->d[j-1]==z->d[i-1]) {
z->n=i;
z->m=j-i;
return;
}
}
}
}
中避免使用i和j,因此它们在这些循环中的使用与我的使用不会发生冲突。
其中一些材料之前已发布到comp.lang.c,并且有一个链接视频,这是对整个主题的精彩介绍。