Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更有效的解决方案:Project Euler#2:偶数斐波那契数_Java_Algorithm - Fatal编程技术网

Java 更有效的解决方案:Project Euler#2:偶数斐波那契数

Java 更有效的解决方案:Project Euler#2:偶数斐波那契数,java,algorithm,Java,Algorithm,问题: 斐波那契序列中的每个新项都是通过添加 前两届 从1和2开始,前10个术语将 是: 1,2,3,5,8,13,21,34,55,89,… 通过考虑Fibonacci序列中的项,其值不 超过四百万,求偶数项之和 我的代码:(很好用) 我正在寻找一个更有效的算法来解决这个问题。有什么提示吗?你不能再改进了,你所做的任何改进都可以忽略不计,而且取决于你运行的操作系统 示例: 在我的Mac上以循环方式运行代码1M次73-75毫秒(运行了几次)。 更改条件: if(newFib % 2 == 0){

问题:

斐波那契序列中的每个新项都是通过添加 前两届

从1和2开始,前10个术语将 是:

1,2,3,5,8,13,21,34,55,89,…

通过考虑Fibonacci序列中的项,其值不 超过四百万,求偶数项之和

我的代码:(很好用)


我正在寻找一个更有效的算法来解决这个问题。有什么提示吗?

你不能再改进了,你所做的任何改进都可以忽略不计,而且取决于你运行的操作系统

示例:
在我的Mac上以循环方式运行代码1M次73-75毫秒(运行了几次)。
更改条件:

if(newFib % 2 == 0){
致:

再运行几次,我得到51-54毫秒

  • 如果你要在不同的操作系统上运行相同的东西,你可能(和 可能会)得到不同的结果
  • 即使我们将上述考虑作为一种改进,在1M中分为20MS,对于单次运行来说,“改进”是没有意义的(20纳米)。李>
在考虑以下规则时:

偶数+偶数=偶数

偶数+奇数=奇数

奇数+偶数=奇数

奇数+奇数=偶数

第一个斐波那契数的奇偶性为:

欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧

因此,基本上,您只需要执行三个步骤。即:

(1,1,2)
(3,5,8)
(13,21,34)
给定
(a,b,c)
这是
(b+c,b+2*c,2*b+3*c)

这意味着我们只需要存储最后两个数字,并计算给定的
(a,b)
(a+2*b,2*a+3*b)

因此,
(1,2)->(5,8)->(21,34)->……
并始终返回最后一个

这将比“过滤器”方法工作得更快,因为它使用if语句,从而减少了管道


生成的代码是:

int b = 1;
int c = 2, d;
long sum = 0;
while(c < 4000000) {
    sum += c;
    d = b+(c<<0x01);
    c = d+b+c;
    b = d;
}
System.out.println(sum);
intb=1;
int c=2,d;
长和=0;
而(c<4000000){
总和+=c;

正如我在评论中提到的,实际上没有必要进一步改进。 我做了一些测量

  • 循环了100万次
  • 以[ms]为单位测量时间
  • ms/1000000=ns
  • 因此单次通过时间[ns]如下:

  • [176 ns]-利用偶数每三分之一
  • [179 ns]-&1而不是%2
  • [169 ns]-&1而不是%2,如果通过-,^,&
    [edit1]新代码
  • [105 ns]-利用每三分之一个偶数+衍生的fibonaci双迭代 [edit2]新代码
  • [76 ns]-减少操作数计数以降低开销和堆损坏
  • 最后一个显然在我的机器上获胜(尽管我希望第一个会是最好的)

  • 所有测试均在Win7 x64 AMD A8-5500 3.2GHz上进行
  • 无线程应用程序32位编译器BDS2006 Trubo C++

  • 答案中已经很好地提到了1,2,所以我只评论了3:

    s+=a&(-((a^1)&1));
    
  • (a^1)否定最爱的位

  • ((a^1)和1)为1表示偶数,为0表示奇数a
  • -((a^1)和1))是-1表示偶数,0表示奇数a
  • -1是0xFFFFFF,因此通过它对数字进行anding不会改变它
  • 0是0x00000000,因此它的AND数将是0
  • 因此,如果
  • 你也可以用否定代替异或,但是在我的机器上速度要慢得多
好的,这是代码(如果您想自己编写代码,请不要进一步阅读):

//---------------------------------------------------------------------------
int euler002()
{
//斐波那契序列中的每个新项都是通过将前两项相加生成的。
//从1和2开始,前10个术语将是:1、2、3、5、8、13、21、34、55、89。。。
//通过考虑Fibonacci序列中值不超过400万的项,求偶数值项之和。
int a,a0=0,a1=1,s=0,N=4000000;
/*
//1.[176纳秒]
a=a0+a1;a0=a1;a1=a;//奇数
a=a0+a1;a0=a1;a1=a;//偶数
对于(;a=N)断裂;
如果((a&1)=0)s+=a;
}
//3.[169纳秒]
对于(;;)
{
a=a0+a1;a0=a1;a1=a;
如果(a>=N)中断;
s+=a&(((a^1&1));
}
//4.[105 ns]/[edit1]
a0+=a1;a1+=a0;a=a1;//2x

对于(;a假设连续斐波那契数

a, b,
c =  a +  b,
d =  a + 2b,
e = 2a + 3b,
f = 3a + 5b,
g = 5a + 8b = a + 4(a + 2b) = a + 4d,
使用

ef0=0,ef1=2,efn=efn-2+4 efn-1

项目Euler问题2的答案是(用Java):

intx=0;
int y=1;
intz=x+y;
int-sumeen=0;
而(z<4000000){
x=y;
y=z;
z=x+y;
如果(z%2==0){
sumeen+=z;///或sumeen=sumeen+z
}
}
System.out.printf(“偶数值项之和:%d\n”,sumeven);
这是最简单的答案。

F(n)是第n个Fibonnaci数,即F(n)=F(n-1)+F(n-2)
假设F(n)是偶数,那么
F(n)=F(n-1)+F(n-2)=F(n-2)+F(n-3)+F(n-2)
F(n)=2F(n-2)+F(n-3)
--这证明了每三项都是偶数(如果F(n-3)是偶数,那么F(n)也必须是偶数)

F(n)=2[F(n-3)+F(n-4)]+F(n-3)
=3F(n-3)+2F(n-4)
=3F(n-3)+2F(n-5)+2F(n-6)

根据公式1:
F(n-3)=2F(n-5)+F(n-6)
2F(n-5)=F(n-3)-F(n-6)

F(n)=3F(n-3)+[F(n-3)-F(n-6)]+2F(n-6)
=4F(n-3)+F(n-6)

如果偶数序列由每三个数组成(n,n-3,n-6,…)

偶数斐波那契序列:
E(k)=4E(k-1)+E(k-2)
Fib序列F={0,1,1,2,3,5,8…}
偶Fib序列E={0,2,8,…}
代码:

 public static long findEvenFibSum(long n){
     long term1=0;
     long term2=2;
     long curr=0;
     long sum=term1+term2;          
        while((curr=(4*term2+term1))<=n){
            sum+=curr;
            term1=term2;
            term2=curr;             
        }
  return sum;
  }
公共静态长findevinfibsum(长n){
长期1=0;
长期2=2;
长电流=0;
长和=第1项+第2项;
wh
//---------------------------------------------------------------------------
int euler002()
    {
    // Each new term in the Fibonacci sequence is generated by adding the previous two terms.
    // By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
    // By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
    int a,a0=0,a1=1,s=0,N=4000000;
/*
    //1. [176 ns]
    a=a0+a1; a0=a1; a1=a;   // odd
    a=a0+a1; a0=a1; a1=a;   // even
    for (;a<N;)
        {
        s+=a;
        a=a0+a1; a0=a1; a1=a;   // odd
        a=a0+a1; a0=a1; a1=a;   // odd
        a=a0+a1; a0=a1; a1=a;   // even
        }

    //2. [179 ns]
    for (;;)
        {
        a=a0+a1; a0=a1; a1=a;
        if (a>=N) break;
        if ((a&1)==0) s+=a;
        }
    //3. [169 ns]
    for (;;)
        {
        a=a0+a1; a0=a1; a1=a;
        if (a>=N) break;
        s+=a&(-((a^1)&1));
        }
    //4. [105 ns] // [edit1]
    a0+=a1; a1+=a0; a=a1;       // 2x
    for (;a<N;)
        {
        s+=a; a0+=a1; a1+=a0;   // 2x
        a=a0+a1; a0=a1; a1=a;   // 1x
        }
*/
    //5. [76 ns] //[ edit2]
    a0+=a1; a1+=a0;             // 2x
    for (;a1<N;)
        {
        s+=a1; a0+=a1; a1+=a0;  // 2x
        a=a0; a0=a1; a1+=a;     // 1x
        }

    return s;
    }
//---------------------------------------------------------------------------
a, b,
c =  a +  b,
d =  a + 2b,
e = 2a + 3b,
f = 3a + 5b,
g = 5a + 8b = a + 4(a + 2b) = a + 4d,
int x = 0;
int y = 1;
int z = x + y;
int sumeven = 0;
while(z < 4000000){
    x = y;
    y = z;
    z = x + y;
    if(z % 2 == 0){
        sumeven += z; /// OR sumeven = sumeven + z
    }
}
System.out.printf("sum of the even-valued terms: %d \n", sumeven);
 public static long findEvenFibSum(long n){
     long term1=0;
     long term2=2;
     long curr=0;
     long sum=term1+term2;          
        while((curr=(4*term2+term1))<=n){
            sum+=curr;
            term1=term2;
            term2=curr;             
        }
  return sum;
  }
34 = 4*8 + 2,
144 = 34*4 + 8,
610 = 144*4 + 34;
Even(n)=4*Even(n-1)+E(n-2);
public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int t = in.nextInt();
    for(int a0 = 0; a0 < t; a0++){
        long n = in.nextLong();
        long a=2;
        long b=8;
        long c=0;
        long sum=10;
        while(b<n)
        {
            sum +=c;
            c=b*4+a;
            a=b;
            b=c;     
        }
        System.out.println(sum);
    }
}