RosettaCodeData/Task/Continued-fraction/Rust/continued-fraction.rust

46 lines
1.5 KiB
Plaintext

use std::iter;
// Calculating a continued fraction is quite easy with iterators, however
// writing a proper iterator adapter is less so. We settle for a macro which
// for most purposes works well enough.
//
// One limitation with this iterator based approach is that we cannot reverse
// input iterators since they are not usually DoubleEnded. To circumvent this
// we can collect the elements and then reverse them, however this isn't ideal
// as we now have to store elements equal to the number of iterations.
//
// Another is that iterators cannot be resused once consumed, so it is often
// required to make many clones of iterators.
macro_rules! continued_fraction {
($a:expr, $b:expr ; $iterations:expr) => (
($a).zip($b)
.take($iterations)
.collect::<Vec<_>>().iter()
.rev()
.fold(0 as f64, |acc: f64, &(x, y)| {
x as f64 + (y as f64 / acc)
})
);
($a:expr, $b:expr) => (continued_fraction!($a, $b ; 1000));
}
fn main() {
// Sqrt(2)
let sqrt2a = (1..2).chain(iter::repeat(2));
let sqrt2b = iter::repeat(1);
println!("{}", continued_fraction!(sqrt2a, sqrt2b));
// Napier's Constant
let napiera = (2..3).chain(1..);
let napierb = (1..2).chain(1..);
println!("{}", continued_fraction!(napiera, napierb));
// Pi
let pia = (3..4).chain(iter::repeat(6));
let pib = (1i64..).map(|x| (2 * x - 1).pow(2));
println!("{}", continued_fraction!(pia, pib));
}