/// Iterator producing successive approximations of π using the Nilakantha series.
pubstructPiSpigot{
k: u64,
current: f64,
}
implIteratorforPiSpigot{
typeItem=f64;
fnnext(&mutself)-> Option<Self::Item>{
ifself.k==0{
self.k=1;
self.current=3.0;
returnSome(self.current);
}
letk=self.kasf64;
letterm=4.0/((2.0*k)*(2.0*k+1.0)*(2.0*k+2.0));
ifself.k%2==1{
self.current+=term;
}else{
self.current-=term;
}
self.k+=1;
Some(self.current)
}
}
/// Generator yielding approximations of π indefinitely.
pubfnpi_spigot()-> PiSpigot{
PiSpigot{k: 0,current: 0.0}
}
/// Return the first `n` approximations of π as a vector.
pubfnpi_values(n: usize)-> Vec<f64>{
pi_spigot().take(n).collect()
}
/// Generator yielding approximations of τ = 2π indefinitely.
pubfntau_spigot()-> implIterator<Item=f64>{
pi_spigot().map(|v|v*2.0)
}
/// Return the first `n` approximations of τ as a vector.
pubfntau_values(n: usize)-> Vec<f64>{
tau_spigot().take(n).collect()
}
/// Iterator producing successive approximations of the Euler-Mascheroni constant γ.
pubstructGammaSpigot{
n: u64,
harmonic: f64,
}
implIteratorforGammaSpigot{
typeItem=f64;
fnnext(&mutself)-> Option<Self::Item>{
self.n+=1;
self.harmonic+=1.0/self.nasf64;
letvalue=self.harmonic-(self.nasf64).ln();
Some(value)
}
}
/// Generator yielding approximations of γ indefinitely.
pubfngamma_spigot()-> GammaSpigot{
GammaSpigot{
n: 0,
harmonic: 0.0,
}
}
/// Return the first `n` approximations of γ as a vector.
pubfngamma_values(n: usize)-> Vec<f64>{
gamma_spigot().take(n).collect()
}
/// Iterator producing successive approximations of e using the series Σ 1/n!.
pubstructESpigot{
n: u64,
sum: f64,
factorial: f64,
}
implIteratorforESpigot{
typeItem=f64;
fnnext(&mutself)-> Option<Self::Item>{
ifself.n==0{
self.n=1;
self.sum=1.0;
self.factorial=1.0;
returnSome(self.sum);
}
self.factorial*=self.nasf64;
self.sum+=1.0/self.factorial;
self.n+=1;
Some(self.sum)
}
}
/// Generator yielding approximations of e indefinitely.
pubfne_spigot()-> ESpigot{
ESpigot{
n: 0,
sum: 0.0,
factorial: 1.0,
}
}
/// Return the first `n` approximations of e as a vector.
pubfne_values(n: usize)-> Vec<f64>{
e_spigot().take(n).collect()
}
/// Iterator producing successive approximations of √2 using Newton's method.
pubstructSqrt2Spigot{
x: f64,
first: bool,
}
implIteratorforSqrt2Spigot{
typeItem=f64;
fnnext(&mutself)-> Option<Self::Item>{
ifself.first{
self.first=false;
Some(self.x)
}else{
self.x=0.5*(self.x+2.0/self.x);
Some(self.x)
}
}
}
/// Generator yielding approximations of √2 indefinitely.
pubfnsqrt2_spigot()-> Sqrt2Spigot{
Sqrt2Spigot{
x: 1.0,
first: true,
}
}
/// Return the first `n` approximations of √2 as a vector.
pubfnsqrt2_values(n: usize)-> Vec<f64>{
sqrt2_spigot().take(n).collect()
}
fnlook_and_say(s: &str)-> String{
letmutchars=s.chars().peekable();
letmutresult=String::new();
whileletSome(c)=chars.next(){
letmutcount=1;
whileletSome(&next)=chars.peek(){
ifnext==c{
chars.next();
count+=1;
}else{
break;
}
}
result.push_str(&format!("{}{}",count,c));
}
result
}
/// Iterator producing successive ratios of lengths of the look-and-say sequence.
pubstructConwaySpigot{
current: String,
}
implIteratorforConwaySpigot{
typeItem=f64;
fnnext(&mutself)-> Option<Self::Item>{
letnext=look_and_say(&self.current);
letratio=next.len()asf64/self.current.len()asf64;
self.current=next;
Some(ratio)
}
}
/// Generator yielding approximations of Conway's constant λ indefinitely.
pubfnconway_spigot()-> ConwaySpigot{
ConwaySpigot{
current: "1".to_string(),
}
}
/// Return the first `n` approximations of Conway's constant as a vector.
pubfnconway_values(n: usize)-> Vec<f64>{
conway_spigot().take(n).collect()
}
#[cfg(test)]
modtests{
usesuper::*;
usestd::f64::consts::{E,PI,TAU};
#[test]
fntest_pi_spigot(){
letvals=pi_values(1000);
letapprox=vals.last().cloned().unwrap();
assert!((approx-PI).abs()<1e-8);
}
#[test]
fntest_tau_spigot(){
letvals=tau_values(1000);
letapprox=vals.last().cloned().unwrap();
assert!((approx-TAU).abs()<1e-8);
}
#[test]
fntest_gamma_spigot(){
letvals=gamma_values(100000);
letapprox=vals.last().cloned().unwrap();
letgamma_true=0.5772156649015329_f64;
assert!((approx-gamma_true).abs()<1e-5);
}
#[test]
fntest_e_spigot(){
letvals=e_values(10);
letapprox=vals.last().cloned().unwrap();
assert!((approx-E).abs()<1e-6);
}
#[test]
fntest_sqrt2_spigot(){
letvals=sqrt2_values(6);
letapprox=vals.last().cloned().unwrap();
assert!((approx-2_f64.sqrt()).abs()<1e-12);
}
#[test]
fntest_conway_spigot(){
letvals=conway_values(25);
letapprox=vals.last().cloned().unwrap();
letconway=1.3035772690342964_f64;
assert!((approx-conway).abs()<1e-2);
}
}
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.