C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: C# 関数選択の質問


(過去ログ 148 を表示中)

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■86346 / inTopicNo.1)  C# 関数選択の質問
  
□投稿者/ DK (1回)-(2018/01/22(Mon) 12:51:25)

分類:[C#] 

ボタンを押すと計算を行うプログラムを作成していますが、
コンボボックスの選択で計算を行う関数を切替させることをしたいです。
下記のようなコードでコンボボックスで選択されているインデックスに応じた
繰り返し計算を行わせていますが、どうしてもfor文の中にif文を入れてしまうと
処理時間が大きくなってしまいます。



public partial class Form1 : Form
{

   double function1(double x)
   {
     return x*x;
   }

   double function2(double x)
   {
     return x*x*x;
   }
   

・・・

private void button6_Click(object sender, EventArgs e)
{
   for(int a=0; a<1000000; a++)
   {
      if(comboBox1.SelectedIndex==1)
      {
          y = function1(x);
      }
      else
      {
          y = function2(x);
      }
   }
}


for文の中にif文を入れ込まずに、
前段のところでコンボボックスで選択した関数を使う、
のようなことはできないのでしょうか?


public partial class Form1 : Form
{

      if(comboBox1.SelectedIndex==1)
      {
         double function(double x)
         {
           return x*x;
         }
      }
      else
      {
         double function(double x)
         {
           return x*x*x;
         }
      }

素人的質問で申し訳ないです。

引用返信 編集キー/
■86347 / inTopicNo.2)  Re[1]: C# 関数選択の質問
□投稿者/ WebSurfer (1414回)-(2018/01/22(Mon) 13:20:51)
No86346 (DK さん) に返信

> どうしてもfor文の中にif文を入れてしまうと処理時間が大きくなってしまいます。

ホントにそこがボトルネックになっているのかという話はちょっと置いといて・・・

アップされてるコードが変なのもちょっと置いといて、1000000 回 if(comboBox1.SelectedIndex==1) の
判定をすることが問題ということであれば、それはアップされたコードを少し変えれば(if 文をループ
の外に出せば)避けることができると思うのですが?
引用返信 編集キー/
■86348 / inTopicNo.3)  Re[1]: C# 関数選択の質問
□投稿者/ 774RR (584回)-(2018/01/22(Mon) 13:25:47)
C/C++ では関数ポインタを使う案件だね。 C# だと delegate だろうか。

public delegate double Funcd(double d);
void TestFunc()
{
    Funcd f = new Funcd(function1);
    Debug.WriteLine(f(1.0));
}

提示ソースだと Math.Pow() を使うだけのような気のせいがするけど・・・
イベントハンドラ内にて乗数を記憶すればよい

引用返信 編集キー/
■86358 / inTopicNo.4)  Re[2]: C# 関数選択の質問
□投稿者/ ぶなっぷ (161回)-(2018/01/22(Mon) 18:52:00)
double function2(double x)
{
    return x * x;
}

double function3(double x)
{
    return x * x * x;
}

みたいにメソッドを定義して、

Func<double, double> function =
    (comboBox1.SelectedIndex==1) ?
    function2 :
    function3;

あとは、
     for(int x=0; x<1000000; x++)
     {
         function(x);
     }
かな。

Funcっていうのは、あらかじめ用意されているdelegateです。
  >  public delegate TResult Func<in T, out TResult>(T arg);
これ使えば、わざわざ定義しなくてもいいので楽ちんです。

引用返信 編集キー/
■86360 / inTopicNo.5)  Re[3]: C# 関数選択の質問
□投稿者/ furu (155回)-(2018/01/23(Tue) 10:13:47)
2018/01/23(Tue) 10:28:50 編集(投稿者)
No86358 (ぶなっぷ さん) に返信
> Func<double, double> function =
>     (comboBox1.SelectedIndex==1) ?
>     function2 :
>     function3;
> 
> あとは、
>      for(int x=0; x<1000000; x++)
>      {
>          function(x);
>      }
> かな。

ぶなっぷさん、これだとfor文の中にif文が入ったままではないですか?


Func<double, double> function1 => x =>
{
    return x*x;
};
		
Func<double, double> function2 => x =>
{
    return x*x*x;
};

と定義して

    var function =
        (comboBox1.SelectedIndex==1) ?
            function1 :
            function2;

     for(int x=0; x<1000000; x++)
     {
         function(x);
     }

※日本語の間違いを修正しました。

引用返信 編集キー/
■86361 / inTopicNo.6)  Re[3]: C# 関数選択の質問
□投稿者/ ipos (1回)-(2018/01/23(Tue) 10:45:31)
この質問に興味があったので、横から失礼します。

ループで毎回comboBox1.SelectedIndexを参照するのは
もしかしたらコストが累積しそうに思いますが、
単純なif文でもそれなりにコストがかかるのでしょうか?

例えば、(comboBox1.SelectedIndex==1)の条件を外だしして、
以下のように(あるいは三項演算)しても、
やっぱり遅くなるものなのでしょうか?

private void button6_Click(object sender, EventArgs e)
{
   bool f = (comboBox1.SelectedIndex==1);
   for(int a=0; a<1000000; a++)
   {
      if(f)
      {
          y = function1(x);
      }
      else
      {
          y = function2(x);
      }
   }
}

引用返信 編集キー/
■86362 / inTopicNo.7)  Re[4]: C# 関数選択の質問
□投稿者/ 魔界の仮面弁士 (1544回)-(2018/01/23(Tue) 11:07:53)
No86360 (furu さん) に返信
> ぶなっぷさん、これだとfor文の中にif文が入ったままではないですか?

そもそも「if」はどこにも書かれていないので、
「(comboBox1.SelectedIndex==1)」の判定の事でしょうか。

だとしたらその判定は for に入る前に行われます。
ただし No86358
>> Func<double, double> function =
>>  (comboBox1.SelectedIndex==1) ?
>>  function2 :
>>  function3;
だとコンパイルエラーになってしまうので、

Func<double, double> function =
   (comboBox1.SelectedIndex == 1) ?
   (Func<double, double>) function2 :
   (Func<double, double>) function3 ;

あるいは

var function = (comboBox1.SelectedIndex == 1)
       ? (Func<double, double>) function2 : function3 ;

のようにキャストして、三項演算子が指し示す条件式のデリゲート型を
明示しておく必要があります。

一方 No86360 の furu さんのコードは、デリゲート型が
最初から明示されているので、追加のキャストは不要です。
引用返信 編集キー/
■86363 / inTopicNo.8)  Re[4]: C# 関数選択の質問
□投稿者/ 魔界の仮面弁士 (1545回)-(2018/01/23(Tue) 11:32:04)
No86361 (ipos さん) に返信
> ループで毎回comboBox1.SelectedIndexを参照するのは
> もしかしたらコストが累積しそうに思いますが、

SelectedIndex プロパティの内部実装は、
下記のようになっていますので、実行コストは大きいですね。
https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/ComboBox.cs,951aeacaf803a174


> 単純なif文でもそれなりにコストがかかるのでしょうか?

bool 型変数に受け取っておくことで、実行コストを十分に小さくできますね。


参考までに、当方の環境では
 SelectedIndex 判定を 100 万回実行すると、1.00 秒程度
 SelectedIndex 判定を 1000万回実行すると、10.3 秒程度
を要しました。

一方、SelectedIndex 判定の結果を bool 型変数に受けてから
bool 型変数 の判定を 1000万回実行すると、0.03 秒程度でした。
引用返信 編集キー/
■86364 / inTopicNo.9)  Re[5]: C# 関数選択の質問
□投稿者/ furu (156回)-(2018/01/23(Tue) 11:37:37)
No86362 (魔界の仮面弁士 さん) に返信
> ■No86360 (furu さん) に返信
> そもそも「if」はどこにも書かれていないので、
> 「(comboBox1.SelectedIndex==1)」の判定の事でしょうか。
>
> だとしたらその判定は for に入る前に行われます。

魔界の仮面弁士さん、ご指摘ありがとうございます。

ぶなっぷさん、申し訳ございません。
=>と勘違いしてました。
引用返信 編集キー/
■86367 / inTopicNo.10)  Re[5]: C# 関数選択の質問
□投稿者/ ipos (2回)-(2018/01/23(Tue) 12:13:51)
No86363 (魔界の仮面弁士 さん) に返信
> ■No86361 (ipos さん) に返信
>>ループで毎回comboBox1.SelectedIndexを参照するのは
>>もしかしたらコストが累積しそうに思いますが、
>
> SelectedIndex プロパティの内部実装は、
> 下記のようになっていますので、実行コストは大きいですね。
> https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/ComboBox.cs,951aeacaf803a174
>
>
>>単純なif文でもそれなりにコストがかかるのでしょうか?
>
> bool 型変数に受け取っておくことで、実行コストを十分に小さくできますね。

ご回答ありがとうございました。
他人の立てたスレッドでの質問で大変恐縮ですが、
恐らく本来の質問者様にも有用な情報となったのではないか、と思いますので、
ご容赦ください。m(__)m
引用返信 編集キー/
■86384 / inTopicNo.11)  Re[6]: C# 関数選択の質問
□投稿者/ ぶなっぷ (162回)-(2018/01/25(Thu) 09:50:46)
遅くなってすいません。

furuさん
  いえいえ、お互い切磋琢磨しましょう。

魔界の仮面弁士 さん
  コードを書いて確認してみました。
  確かに、暗黙のキャストしてくれないんですね。
  動かして確認していないのがもろばれですね(笑)

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -