mysql做乘法运算溢出_乘法溢出及对策
最近幾次碰到乘法溢出,
情況一:
下面是修訂后的版本
void dfs(int pos, int lim, int val, int div)
{
int i,j;
if(pos>prime[0]||prime[pos]>lim) return;
int t=prime[pos];
for(i=1,j=1; i<=lim/t;j++){
i*=t;
divisor[val*i]=div*(j+1);
dfs(pos+1,lim/i,val*i,div*(j+1));
}
dfs(pos+1,lim,val,div);
}
原來的版本是for(i=1,j=1; i*t<=lim;j++),結果i*t溢出變成負數導致divisor[val*i]的下標為負
情況二多一個乘法,導致顧此失彼: LIMIT 是500000,在下面的for循環
for(t=prime[ob.ind];t<=LIM/ob.cur;t*=prime[ob.ind])
t是第4793個質數46349,ob.cur為8,導致t*=prime[ob.ind]會產生乘法溢出(超過2^31-1),其實t<=LIM/ob.cur已經是為了避免乘法溢出的做法,結果還是沒有考慮到后面的乘法。
程序運行最終產生了access violation(VC),因為divs[t*ob.cur]的下標出現了一個大負數。
解決的辦法:因為這是都不超過int的范圍,將相關類型擴展成long long就解決了。當然也可以采用上面的方式。
struct frame{
int ind,cur,cur_div;
frame(int i,int c, int d):ind(i),cur(c),cur_div(d){}
};
void dfs(int ind, int cur, int cur_div)
{
stackst;
st.push(frame(ind,cur,cur_div));
while(!st.empty()){
frame ob=st.top();
st.pop();
if(ob.ind==prime[0]+1 || ob.cur>LIM/prime[ob.ind]) continue;
st.push(frame(ob.ind+1,ob.cur,ob.cur_div));
int t,tot=1;
for(t=prime[ob.ind];t<=LIM/ob.cur;t*=prime[ob.ind]){
tot+=t;
divs[t*ob.cur]=ob.cur_div*tot;
st.push(frame(ob.ind+1,ob.cur*t,ob.cur_div*tot));
}
}
}
最新的情況
要求 prime[i]^p * prime[i+k]^(p+t)<=10^9? prime[i+k]^(p+t)本身可能超過10^9,對數取整也許可以解除所有溢出煩惱,唯一不確定的就是浮點類型精度是損失是否會帶來不可接受的誤差
p*log10((double)prime[i])+(p+t)*log10((double)prime[i+k])<=9.0
閱讀(1957) | 評論(0) | 轉發(0) |
總結
以上是生活随笔為你收集整理的mysql做乘法运算溢出_乘法溢出及对策的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信息学奥赛一本通 1232:Crossi
- 下一篇: java gridout_GridBag