2017-03-20 6 views
3

I found a function to compute a meanと一緒に遊んでいます。以下のコードスニペットが実行されますが、入力内のデータがfloatからintに変化するとエラーが発生します。浮動小数点数と整数でどのように動作させるには?関数が整数または浮動小数点数を扱えるようにするにはどうすればよいですか?

use std::borrow::Borrow; 

fn mean(arr: &mut [f64]) -> f64 { 
    let mut i = 0.0; 
    let mut mean = 0.0; 
    for num in arr { 
     i += 1.0; 
     mean += (num.borrow() - mean)/i; 
    } 
    mean 
} 

fn main() { 
    let val = mean(&mut vec![4.0, 5.0, 3.0, 2.0]); 
    println!("The mean is {}", val); 
} 
+1

"整数で作業する"と言うとき、戻り値の型は何か:整数か浮動小数点か? @MatthieuM。 –

+0

。選択されたアルゴリズムで判断すると、OPはいつも 'f64'を返すものが好きですが、整数入力も受け付けます。 – user4815162342

+0

私が思っていない 'num' crateも不十分だと見てください。例えば、 – user25064

答えて

7

f64borrow()メソッドを持っていないので、問題のコードはコンパイルされません。また、受け入れるスライスは変更しないので変更する必要はありません。ここでコンパイルして動作します修正版です:

fn mean(arr: &[f64]) -> f64 { 
    let mut i = 0.0; 
    let mut mean = 0.0; 
    for num in arr.iter() { 
     i += 1.0; 
     mean += (num - mean)/i; 
    } 
    mean 
} 

は整数を受け入れるには、機能がジェネリックする必要があります。理想的には、整数だけでなく、などのf64に変換できるタイプまたはユーザー提供のデータタイプを受け入れることが理想的です。 x as f64を任意xのために定義されていないので、これはコンパイルされません

fn mean<T>(arr: &[T]) -> f64 { 
    let mut i = 0.0; 
    let mut mean = 0.0; 
    for num in arr.iter() { 
     i += 1.0; 
     mean += (num as f64 - mean)/i; 
    } 
    mean 
} 

:次のように書くことがいいだろう。その代わりに、Tの値にTの値をf64に変換する方法を定義する特性が必要です。これはまさにInto traitの目的です。 Into<U>を実装するすべてのタイプTinto(self) -> Uメソッドを定義します。特性バインドとしてT: Into<f64>を指定するとinto()メソッドが返され、f64が返されます。

またTCopyとする必要があります。そのため、Rustは、配列の値が変換によって「消費」(移動)されないことを認識します。整数はCopyを実装しているので、これは私たちにとっては問題ありません。これが唯一のf64からロスレス変換を定義するタイプのために働くことを

fn mean<T: Into<f64> + Copy>(arr: &[T]) -> f64 { 
    let mut i = 0.0; 
    let mut mean = 0.0; 
    for num in arr.iter() { 
     i += 1.0; 
     mean += ((*num).into() - mean)/i; 
    } 
    mean 
} 

fn main() { 
    let val1 = mean(&vec![4.0, 5.0, 3.0, 2.0]); 
    let val2 = mean(&vec![4, 5, 3, 2]); 
    println!("The means are {} and {}", val1, val2); 
} 

注:作業するコードは次のようになります。従って、u32,i32(上記の例のような)とそれより小さい整数型では動作しますが、i64またはu64のベクトルは受け入れられません。これは無損失でf64に変換できません。

また、この問題は、enumerate()fold()などの関数型プログラミングイディオムにはうまく当てはまることにも注意してください。このような実装を書くことは、すでに長めの答えの範囲外ですが、エクササイズhard to resistです。

+0

のように 'sum'や' product'のような関数に使うことができる '' 0''と '' one''特性を定義します。注意:この例では、 'val2'は' Vec 'を使い、 'i32 '' f64'への可逆変換があり、 'Into 'が実装されています。しかし、私はそれが 'i64'でうまくいくとは思わない。 @MatthieuM。 –

+0

このような動作は、ユーザーが期待するものではないかもしれないが、合理的なデフォルトのように聞こえる。私は今答えを明示的に言及しました。 – user4815162342

+1

合理的ですが、私は「完全な開示」を好むだけです。いい答え :) –

関連する問題