标签:java performance long-integer math
Stackoverflow的新功能所以请指出我可以做的任何事情来提高我的问题的质量.
所以我的代码所做的(或者更确切地说是希望做的)是计算巨大的斐波纳契数,模数非常大.为了使算法更有效,我使用了pisano periods.本质上,我计算了m的pisano周期,然后使用以下关系更容易计算余数:
The remainder of the n th Fibonacci number (modulo m) is equal to the remainder of the k th Fibonacci number (modulo m) such that k = n % p where p is the pisano period of m.
为了计算pisano时期,我使用以下属性:
If the current Fib % m = 0 and the sum of all Fib’s until now % m = 0, then the index of the current Fib is the pisano period of m. (Note the index must be greater than 0)
然而,我在这方面遇到了一个问题:为了计算pisano时期,我必须计算连续的Fibonacci数.当必须计算的斐波纳契数的数量变得非常大时,例如100 000,就会出现问题.然后数据类型长溢出.
据我所知,任何计算皮萨诺时期的努力都需要计算斐波那契,所以唯一的解决方案似乎是用其他东西替换长期.如果有人对这个替代品有什么建议,我将不胜感激.
import java.util.*;
public class FibHuge {
public static void main (String [] args) {
Scanner in = new Scanner (System.in);
long num = in.nextLong ();
long mod = in.nextLong();
System.out.println ( getMod(num, mod));
}
private static int getMod (long num, long mod) {
Period per = new Period();
long period = per.getPeriod (mod);
int newFibNum = (int)(num % period);
num = (num % mod);
Integer ia[] = new Integer [per.al.size()];
ia = per.al.toArray (ia);
return ia[newFibNum];
}
}
class Period {
ArrayList <Long> al;
long FNum;
long SNum;
Period () {
al = new ArrayList <Long> ();
FNum = 0;
SNum = 1;
}
private long getFib (long first, long second){
return first + second;
}
long getPeriod (long mod){
boolean bool = true;
long fibcount = 0;
long currentmod = 0;
long fib = 0;
long sum = 0;
while (bool){
if (fibcount <= 1){
currentmod = fibcount % mod;
al.add (currentmod);
sum += fibcount;
}
else {
fib = getFib (FNum, SNum);
FNum = SNum;
SNum = fib;
currentmod = (fib % mod);
al.add (currentmod);
sum += fib;
}
if ( (currentmod == 0 & (sum % mod) == 0) & fibcount > 0){
return fibcount;
}
fibcount++;
}
return mod; //essentially just to satisfy the return condition
}
}
解决方法:
你不需要使用BigInteger,除非你的模数太大而不适合长在这种情况下,我怀疑你会在内存中试图找到解决方案.
不是计算第n个斐波纳契数然后执行模数,您可以使用此属性计算模数后的第n个斐波纳契数
(a + b) % n = (a % n + b % n) % n;
换句话说,您只需要在每次迭代中不断添加数字模数.您可以在Set中保存所有模数值,当您得到重复结果时,您有一个句点.您可以将迭代编号与结果一起存储,并使用它来计算周期.
事实上,模数有点贵,但是因为你只能求一个小于2 *模数的数字,你可以简单地做
long c = a + b; // Fibonacci
if (c >= modulus) c -= modulus; // the only real change you need for modulus.
由于Java使用条件移动而不是实际分支,因此这比使用%快得多
如果不为您编写代码,我无法想到您需要了解的更多细节.
标签:java,performance,long-integer,math 来源: https://codeday.me/bug/20190724/1524838.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。