Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.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
Generics 使用泛型在编译时生成斐波那契序列 在C++中,用模板元编程可以很容易地在编译时计算Fibonacci序列。 模板 constexpr int fibonacci(){返回fibonacci()+fibonacci();} 模板 constexpr int fibonacci(){return 1;} 模板 constexpr int fibonacci(){return 0;}_Generics_Rust_Compile Time - Fatal编程技术网

Generics 使用泛型在编译时生成斐波那契序列 在C++中,用模板元编程可以很容易地在编译时计算Fibonacci序列。 模板 constexpr int fibonacci(){返回fibonacci()+fibonacci();} 模板 constexpr int fibonacci(){return 1;} 模板 constexpr int fibonacci(){return 0;}

Generics 使用泛型在编译时生成斐波那契序列 在C++中,用模板元编程可以很容易地在编译时计算Fibonacci序列。 模板 constexpr int fibonacci(){返回fibonacci()+fibonacci();} 模板 constexpr int fibonacci(){return 1;} 模板 constexpr int fibonacci(){return 0;},generics,rust,compile-time,Generics,Rust,Compile Time,但据我所知,在rust中,不能只通过泛型传递常量,而且我知道有时rust会在assmebly代码中将某些函数优化为常量。例如: 但该问题的传统递归方法并没有优化到一个常数 fn fibo(n:i32)->i32{ 匹配{ 0 => 0, 1 => 1, n=>fibo(n-1)+fibo(n-2), } } //称之为 fibo(45);//运行时计算大约需要5秒 好的,到目前为止,我不能理解只有编译器不知道如何优化它,但是我找到了一种方法,可以在编译时使用迭代器计算它 structfibo(

但据我所知,在rust中,不能只通过泛型传递常量,而且我知道有时rust会在assmebly代码中将某些函数优化为常量。例如:

但该问题的传统递归方法并没有优化到一个常数

fn fibo(n:i32)->i32{
匹配{
0 => 0,
1 => 1,
n=>fibo(n-1)+fibo(n-2),
}
}
//称之为
fibo(45);//运行时计算大约需要5秒
好的,到目前为止,我不能理解只有编译器不知道如何优化它,但是我找到了一种方法,可以在编译时使用迭代器计算它

structfibo(u32,u32);
Fibo的impl迭代器{
项目类型=u32;
fn下一步(&mut self)->选项{
*self=Fibo(self.1,self.1+self.0);
一些(self.0)
}
}
fn fibo()->fibo{
Fibo(0,1)
}
//称之为
收集::()[44];//这将立即获得编译时计算的第45个元素

此时,我只想知道为什么会发生这种情况。

我查看了第二个代码示例的汇编输出,编译器似乎没有将其优化为常数。很可能,正在发生一些非常不同的事情

您称之为“经典”递归算法的方法是计算斐波那契数的最糟糕的方法,因为函数调用的数量随着
n
呈指数增长。迭代方法要好得多,因为它只需要随着
n
线性增长的迭代次数。对于
n=44
,递归方法大约需要10万亿次函数调用,而迭代方法需要44次循环迭代。当然,后者在运行时看起来是“即时的”,但这并不意味着这里发生了任何特殊的编译器魔法

(对于真正大的
n
您需要任意精度的算法,最好的方法是二进制矩阵加电。)

现在是第二个问题,如何让Rust在编译时对此进行评估。C++中的模板元编程实际上是编译时计算的一个拐杖,RIST有一个更容易的方法:常数函数。const-fns的某些方面仍在发展中,但在当前的beta版(将在大约两周后稳定发布)中,您可以用一种非常简单的方式编写斐波那契函数:

pub const fn fibo(mut n: u64) -> u64 {
    let mut a = 1;
    let mut b = 0;
    while n > 0 {
        let tmp = b;
        b += a;
        a = tmp;
        n -= 1;
    }
    b
}

pub const K: u64 = fibo(93);
()

Rust中也有const泛型,但它们是不稳定的(而且仍然相当不稳定)。你可以做类似于C++模板元编程的东西,但是我没有研究它。

<代码> const fn FiBO(n:i32)-> i32 { 匹配{ 0 => 0, 1 => 1, n=>fibo(n-1)+fibo(n-2), } } 常数A:i32=fibo(45); 此代码将在编译时计算。
但是要花很长时间来编译它,而且它不能在操场上编译。 因此,生锈可能不会优化它。
您还可以查看和ir

算法复杂性 计算斐波那契序列的简单方法具有指数复杂性

fn fibo(n:i32)->i32{
匹配{
0 => 0,
1 => 1,
n=>fibo(n-1)+fibo(n-2),
}
}
您可以将其可视化为:

  • fibo(0)
    :1次呼叫
  • fibo(1)
    :1次呼叫
  • fibo(2)
    :3个调用--
    fibo(2)
    fibo(1)
    fibo(0)
  • fibo(3)
    :5次调用--
    fibo(3)
    fibo(2)
    (值3),
    fibo(1)
  • fibo(4)
    :9次调用--
    fibo(4)
    fibo(3)
    (值5)和
    fibo(2)
    (值3)
但是,迭代器版本完全不同。重写为一个函数,它归结为:

fn fibo(n:i32)->i32{
fn rec(i:i32,当前:i32,下一个:i32)->i32{
如果i==0{current}则{rec(i-1,next,current+next)}
}
记录(n,0,1)
}
它以精确的
n+1
步骤执行。。。提供
n>=0

但是C++中它是有效的! C++编译器倾向于对模板实例化和constexpr求值使用memonization。他们不必这样做,这严格来说是一个实施细节,但他们这样做是出于效率考虑

在本例中,
fibo
的记忆版本将指数复杂度转化为线性复杂度,这更易于计算

在铁锈里做! 可以在编译时使用当前的beta版本计算Rust中的斐波那契,这可以稳定
const
函数中的分支

见:

常量fn fibo(n:i32)->i32{ 常数fn rec(i:i32,当前:i32,下一个:i32)->i32{ 如果i==0{current}则{rec(i-1,next,current+next)} } 记录(n,0,1) } fn main(){ 常数结果:usize=fibo(9)为usize; let数组:[i32;结果]=[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1 ]; println!(“{}”,数组[0]); }
可能有一个技巧可以在编译时不使用分支来表示计算,允许在stable上的编译时计算
fibo
,但是我不确定rustc是否会执行递归调用。

这里有两个问题,它们彼此非常不同。找到一种处理泛型的方法与Rust编译器如何优化此计算无关。。它的运行速度与
Fibo一样快