zoukankan      html  css  js  c++  java
  • “菲波纳锲”数列 计算

    学习真是奇妙,本想查找些异步进程的东西,实践的时候突然发现异步控制UI有些不大一样,于是去查异步更新UI,结果查到了BackgroundWorker,于是去查这个类,又在MSDN上找到了一个示例,是以计算 斐波纳契 数列来显示进度的,示例是这样的

    BackgroundWorker MSDN示例
      1 using System;
      2 using System.Collections;
      3 using System.ComponentModel;
      4 using System.Drawing;
      5 using System.Threading;
      6 using System.Windows.Forms;
      7 
      8 namespace BackgroundWorkerExample
      9 {    
     10     public class FibonacciForm : System.Windows.Forms.Form
     11     {    
     12         private int numberToCompute = 0;
     13         private int highestPercentageReached = 0;
     14 
     15         private System.Windows.Forms.NumericUpDown numericUpDown1;
     16         private System.Windows.Forms.Button startAsyncButton;
     17         private System.Windows.Forms.Button cancelAsyncButton;
     18         private System.Windows.Forms.ProgressBar progressBar1;
     19         private System.Windows.Forms.Label resultLabel;
     20         private System.ComponentModel.BackgroundWorker backgroundWorker1;
     21 
     22         public FibonacciForm()
     23         {    
     24             InitializeComponent();
     25 
     26             InitializeBackgoundWorker();
     27         }
     28 
     29         // Set up the BackgroundWorker object by 
     30         // attaching event handlers. 
     31         private void InitializeBackgoundWorker()
     32         {
     33             backgroundWorker1.DoWork += 
     34                 new DoWorkEventHandler(backgroundWorker1_DoWork);
     35             backgroundWorker1.RunWorkerCompleted += 
     36                 new RunWorkerCompletedEventHandler(
     37             backgroundWorker1_RunWorkerCompleted);
     38             backgroundWorker1.ProgressChanged += 
     39                 new ProgressChangedEventHandler(
     40             backgroundWorker1_ProgressChanged);
     41         }
     42     
     43         private void startAsyncButton_Click(System.Object sender, 
     44             System.EventArgs e)
     45         {
     46             // Reset the text in the result label.
     47             resultLabel.Text = String.Empty;
     48 
     49             // Disable the UpDown control until 
     50             // the asynchronous operation is done.
     51             this.numericUpDown1.Enabled = false;
     52 
     53             // Disable the Start button until 
     54             // the asynchronous operation is done.
     55             this.startAsyncButton.Enabled = false;
     56 
     57             // Enable the Cancel button while 
     58             // the asynchronous operation runs.
     59             this.cancelAsyncButton.Enabled = true;
     60 
     61             // Get the value from the UpDown control.
     62             numberToCompute = (int)numericUpDown1.Value;
     63 
     64             // Reset the variable for percentage tracking.
     65             highestPercentageReached = 0;
     66 
     67             // Start the asynchronous operation.
     68             backgroundWorker1.RunWorkerAsync(numberToCompute);
     69         }
     70 
     71         private void cancelAsyncButton_Click(System.Object sender, 
     72             System.EventArgs e)
     73         {   
     74             // Cancel the asynchronous operation.
     75             this.backgroundWorker1.CancelAsync();
     76 
     77             // Disable the Cancel button.
     78             cancelAsyncButton.Enabled = false;
     79         }
     80 
     81         // This event handler is where the actual,
     82         // potentially time-consuming work is done.
     83         private void backgroundWorker1_DoWork(object sender, 
     84             DoWorkEventArgs e)
     85         {   
     86             // Get the BackgroundWorker that raised this event.
     87             BackgroundWorker worker = sender as BackgroundWorker;
     88 
     89             // Assign the result of the computation
     90             // to the Result property of the DoWorkEventArgs
     91             // object. This is will be available to the 
     92             // RunWorkerCompleted eventhandler.
     93             e.Result = ComputeFibonacci((int)e.Argument, worker, e);
     94         }
     95 
     96         // This event handler deals with the results of the
     97         // background operation.
     98         private void backgroundWorker1_RunWorkerCompleted(
     99             object sender, RunWorkerCompletedEventArgs e)
    100         {
    101             // First, handle the case where an exception was thrown.
    102             if (e.Error != null)
    103             {
    104                 MessageBox.Show(e.Error.Message);
    105             }
    106             else if (e.Cancelled)
    107             {
    108                 // Next, handle the case where the user canceled 
    109                 // the operation.
    110                 // Note that due to a race condition in 
    111                 // the DoWork event handler, the Cancelled
    112                 // flag may not have been set, even though
    113                 // CancelAsync was called.
    114                 resultLabel.Text = "Canceled";
    115             }
    116             else
    117             {
    118                 // Finally, handle the case where the operation 
    119                 // succeeded.
    120                 resultLabel.Text = e.Result.ToString();
    121             }
    122 
    123             // Enable the UpDown control.
    124             this.numericUpDown1.Enabled = true;
    125 
    126             // Enable the Start button.
    127             startAsyncButton.Enabled = true;
    128 
    129             // Disable the Cancel button.
    130             cancelAsyncButton.Enabled = false;
    131         }
    132 
    133         // This event handler updates the progress bar.
    134         private void backgroundWorker1_ProgressChanged(object sender,
    135             ProgressChangedEventArgs e)
    136         {
    137             this.progressBar1.Value = e.ProgressPercentage;
    138         }
    139 
    140         // This is the method that does the actual work. For this
    141         // example, it computes a Fibonacci number and
    142         // reports progress as it does its work.
    143         long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e)
    144         {
    145             // The parameter n must be >= 0 and <= 91.
    146             // Fib(n), with n > 91, overflows a long.
    147             if ((n < 0) || (n > 91))
    148             {
    149                 throw new ArgumentException(
    150                     "value must be >= 0 and <= 91", "n");
    151             }
    152 
    153             long result = 0;
    154 
    155             // Abort the operation if the user has canceled.
    156             // Note that a call to CancelAsync may have set 
    157             // CancellationPending to true just after the
    158             // last invocation of this method exits, so this 
    159             // code will not have the opportunity to set the 
    160             // DoWorkEventArgs.Cancel flag to true. This means
    161             // that RunWorkerCompletedEventArgs.Cancelled will
    162             // not be set to true in your RunWorkerCompleted
    163             // event handler. This is a race condition.
    164 
    165             if (worker.CancellationPending)
    166             {   
    167                 e.Cancel = true;
    168             }
    169             else
    170             {   
    171                 if (n < 2)
    172                 {   
    173                     result = 1;
    174                 }
    175                 else
    176                 {   
    177                     result = ComputeFibonacci(n - 1, worker, e) + 
    178                              ComputeFibonacci(n - 2, worker, e);
    179                 }
    180 
    181                 // Report progress as a percentage of the total task.
    182                 int percentComplete = 
    183                     (int)((float)n / (float)numberToCompute * 100);
    184                 if (percentComplete > highestPercentageReached)
    185                 {
    186                     highestPercentageReached = percentComplete;
    187                     worker.ReportProgress(percentComplete);
    188                 }
    189             }
    190 
    191             return result;
    192         }
    193 
    194 
    195         #region Windows Form Designer generated code
    196         
    197         private void InitializeComponent()
    198         {
    199             this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
    200             this.startAsyncButton = new System.Windows.Forms.Button();
    201             this.cancelAsyncButton = new System.Windows.Forms.Button();
    202             this.resultLabel = new System.Windows.Forms.Label();
    203             this.progressBar1 = new System.Windows.Forms.ProgressBar();
    204             this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
    205             ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
    206             this.SuspendLayout();
    207             // 
    208             // numericUpDown1
    209             // 
    210             this.numericUpDown1.Location = new System.Drawing.Point(16, 16);
    211             this.numericUpDown1.Maximum = new System.Decimal(new int[] {
    212             91,
    213             0,
    214             0,
    215             0});
    216             this.numericUpDown1.Minimum = new System.Decimal(new int[] {
    217             1,
    218             0,
    219             0,
    220             0});
    221             this.numericUpDown1.Name = "numericUpDown1";
    222             this.numericUpDown1.Size = new System.Drawing.Size(80, 20);
    223             this.numericUpDown1.TabIndex = 0;
    224             this.numericUpDown1.Value = new System.Decimal(new int[] {
    225             1,
    226             0,
    227             0,
    228             0});
    229             // 
    230             // startAsyncButton
    231             // 
    232             this.startAsyncButton.Location = new System.Drawing.Point(16, 72);
    233             this.startAsyncButton.Name = "startAsyncButton";
    234             this.startAsyncButton.Size = new System.Drawing.Size(120, 23);
    235             this.startAsyncButton.TabIndex = 1;
    236             this.startAsyncButton.Text = "Start Async";
    237             this.startAsyncButton.Click += new System.EventHandler(this.startAsyncButton_Click);
    238             // 
    239             // cancelAsyncButton
    240             // 
    241             this.cancelAsyncButton.Enabled = false;
    242             this.cancelAsyncButton.Location = new System.Drawing.Point(153, 72);
    243             this.cancelAsyncButton.Name = "cancelAsyncButton";
    244             this.cancelAsyncButton.Size = new System.Drawing.Size(119, 23);
    245             this.cancelAsyncButton.TabIndex = 2;
    246             this.cancelAsyncButton.Text = "Cancel Async";
    247             this.cancelAsyncButton.Click += new System.EventHandler(this.cancelAsyncButton_Click);
    248             // 
    249             // resultLabel
    250             // 
    251             this.resultLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
    252             this.resultLabel.Location = new System.Drawing.Point(112, 16);
    253             this.resultLabel.Name = "resultLabel";
    254             this.resultLabel.Size = new System.Drawing.Size(160, 23);
    255             this.resultLabel.TabIndex = 3;
    256             this.resultLabel.Text = "(no result)";
    257             this.resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
    258             // 
    259             // progressBar1
    260             // 
    261             this.progressBar1.Location = new System.Drawing.Point(18, 48);
    262             this.progressBar1.Name = "progressBar1";
    263             this.progressBar1.Size = new System.Drawing.Size(256, 8);
    264             this.progressBar1.Step = 2;
    265             this.progressBar1.TabIndex = 4;
    266             // 
    267             // backgroundWorker1
    268             // 
    269             this.backgroundWorker1.WorkerReportsProgress = true;
    270             this.backgroundWorker1.WorkerSupportsCancellation = true;
    271             // 
    272             // FibonacciForm
    273             // 
    274             this.ClientSize = new System.Drawing.Size(292, 118);
    275             this.Controls.Add(this.progressBar1);
    276             this.Controls.Add(this.resultLabel);
    277             this.Controls.Add(this.cancelAsyncButton);
    278             this.Controls.Add(this.startAsyncButton);
    279             this.Controls.Add(this.numericUpDown1);
    280             this.Name = "FibonacciForm";
    281             this.Text = "Fibonacci Calculator";
    282             ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
    283             this.ResumeLayout(false);
    284 
    285         }
    286         #endregion
    287 
    288         [STAThread]
    289         static void Main()
    290         {
    291             Application.Run(new FibonacciForm());
    292         }
    293     }
    294 }

    运行之后,输入超过40的数,都很慢,于是去看看算法,于是就有了下面的代码

    View Code
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Diagnostics;
     6 
     7 namespace FibonacciRecursively
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             Program p = new Program();
    14 
    15             const int endNum = 40;
    16 
    17             p.CountTime("尾递归递归",
    18                 new Func<int>(
    19                     () => { return p.FibonacciTailRecursively(endNum, 0, 1); }
    20                     ));
    21 
    22             p.CountTime("循环算法",
    23                 new Func<int>(
    24                     () => { return p.FibonacciLoop(endNum); }
    25                     ));
    26 
    27             
    28             p.CountTime("线性递归",
    29                 new Func<int>(
    30                     () => { return p.FibonacciRecursively(endNum); }
    31                     ));
    32 
    33             Console.ReadKey();
    34         }
    35 
    36         public void CountTime(string name, Func<int> action)
    37         {
    38             Stopwatch sw = new Stopwatch();
    39             sw.Start();
    40 
    41             //要执行的代码
    42             int result=action.Invoke();
    43 
    44             sw.Stop();
    45             Console.WriteLine();
    46             Console.WriteLine(string.Format("{0}:计算结果为:{1}",name,result));
    47             Console.WriteLine("总运行时间:" + sw.Elapsed);
    48             Console.WriteLine("测量实例得出的总运行时间(毫秒为单位):" + sw.ElapsedMilliseconds);
    49         }
    50 
    51         //线性递归
    52         public int FibonacciRecursively(int n)
    53         {
    54             if (n < 2) return n;
    55             return FibonacciRecursively(n - 1) + FibonacciRecursively(n - 2);
    56         }
    57 
    58         //尾递归
    59         public int FibonacciTailRecursively(int n, int acc1, int acc2)
    60         {
    61             if (n == 0) return acc1;
    62             return FibonacciTailRecursively(n - 1, acc2, acc1 + acc2);
    63         }
    64 
    65         //循环算法
    66         public int FibonacciLoop(int n)
    67         {
    68             int result = 0;
    69             int i = 1;
    70             while (n > 0)
    71             {
    72                 int temp = i;
    73 
    74                 i += result;
    75 
    76                 result = temp;
    77                 
    78                 n--;
    79             }
    80             return result;
    81         }
    82 
    83     }
    84 }

    运行结果

    三种计算方式,个人感觉,线性递归的方式更直接,更容易想到,自然也更容易理解,但是效率 惨不忍睹,循环算法和尾递归的方式明显好于线性递归,尾递归给我的感觉更像是把需要的结果都放到了参数里面,省去了系统维护他的参数堆栈,老赵对此做了一定的解释

    http://www.cnblogs.com/JeffreyZhao/archive/2009/04/01/tail-recursion-explanation.html

    还有对于递归与循环的关系,有的说所有的递归都可以用循环代替,有的说不能,我也很困惑,感觉这里有篇文章解释还是比较到位的

    http://blog.sina.com.cn/s/blog_62b1508e0100hcyx.html

  • 相关阅读:
    jquery easy ui 1.3.4 窗口,对话框,提示框(5)
    jquery easy ui 1.3.4 布局layout(4)
    4.1 avd
    android sdk 安装排错
    推荐一个非常COOL的开源相册程序!
    JQuery LazyLoad实现图片延迟加载-探究
    Js和asp.net各自设置的cookie相互读取的方法
    js html5推送 实例
    给网页添加[回到顶部]和[去底部]功能
    Session赋值(备注)
  • 原文地址:https://www.cnblogs.com/goldren/p/2825153.html
Copyright © 2011-2022 走看看