鳩でもわかるC#鳩でもわかるC#C#とJavaScriptをメインに情報発信をしています。数学ネタTweet当ブログはネタ切れをおこすと数学ネタに走る傾向があります。YouTubeで公開されているある動画をみてC#でマンデルブロ集合を描くことに挑戦してみました。ヘロンの数学さんの動画です。極限で無限大に発散しないという条件を満たす複素数が作る集合です。C#では複素数を扱うためのクラスが用意されています。それがSystem.Numerics名前空間のComplexクラスです。これを使うためには参照にSystem.Runtime.Numerics.dllを追加しなければなりません。cを繰り返し計算して一度でもzの絶対値が2を超えてしまうとこの複素数列zは発散してしまうことが証明されています。そこでこんな関数を使えば複素数cに対して複素数列zが発散するかどうか、cがマンデルブロ集合に属するかどうかを調べることができます。cを計算して絶対値zが2を超えなければマンデルブロ集合であると判断します。このメソッドは引数cがマンデルブロ集合に属する場合、trueを返します。true;}}まずは幅800ピクセル、高さ400ピクセルのBitmapをつくります。1ピクセルを0.005として、実部-2から+2、虚部-1から+1まで総当たりで調べます。true;}}するとこのようなこのように描画されます。一応、それっぽいものが描画されています。マンデルブロ集合を拡大して描画する一部を拡大して描画する方法を考えることにします。マンデルブロ集合はフラクタル図形として表され、周囲を拡大すると、このフラクタル図形に類似した飛び地のような図形が無数に見られることが知られています。実際にはマンデルブロ集合全体は「飛び地」のようにみえても実際には連結であることが証明されています。クリックされた場所を中心にして2倍に拡大して表示させることにします。Bitmapの幅と高さが決まっていて中心になる複素数の実部と虚部が決まるのであれば、左上になる複素数の実部と虚部も決まります。最初はBitmapの幅、高さを800ピクセルと400ピクセルにしましたが、マンデルブロ集合は実部は-2から+1未満、虚部も-1から+1以内に収まります。Bitmapは幅650ピクセル、高さ450ピクセルに変更します。中心に表示させるのは実部-0.5、虚部0の部分にします。Bitmap.Height);}}Bitmapの(0,0)の座標にくるのは評価対象となる複素数の実部と虚部の最小値です。中心にくる評価対象となる複素数の値とBitmapのサイズ、1ドットの値から複素数の実部と虚部の最小値は以下のようになります。}}}これをつかってBitmapの中に描画される複素数の範囲内だけマンデルブロ集合に属するかどうかを判定するメソッドを書くとすると以下のようになります。Color.Black);}}}}}クリックされたら拡大する処理マウスが動いたらマウスがある座標はどのような複素数の値に相当する部分なのかがわかるようにタイトルバーに表示させます。{ParDot}";base.OnMouseMove(e);}}そしてクリックされたらその点を中心に拡大/縮小します。0.5;CreateMandelbrotSetBitmap();Invalidate();base.OnMouseDown(e);}}拡大するとマンデルブロ集合らしくなるのはなぜ?これで完成といいたいところなのですが、実際に拡大処理を繰り返してみると繰り返すごとにマンデルブロ集合らしくなくなっていくのです。これは数字の違いがだんだん小さくなっていくからで、最初のほうは30回処理を繰り返して絶対値が2を超えない場合はマンデルブロ集合に属すると判断してもかまわないが、拡大していくにしたがってもっと多くの計算が求められることを意味しています。IsMandelbrotSetメソッドのなかでは30回処理を繰り返して絶対値が2を超えない場合はマンデルブロ集合に属すると判断していますが、処理時間が長くなるけれども30回ではなくもっと増やせばより正確な形になるのではないかと思われます。30回ではなく300回にしてみましょう。すると今度は別の問題がおきます。マンデルブロ集合は連続しているのですが、バラバラの点が目立つようになるのです。これは近くにマンデルブロ集合に属する複素数が存在するが、評価対象の複素数はマンデルブロ集合に属さないからです。そのため点がバラバラに存在するように見えてしまいます。拡大率をあげると連続していることがわかります。そこで最初は反復回数は30回くらいで開始して、拡大率が大きくなったときは反復回数を増やすようにします。当然のことながら反復回数を増やせば処理にかかる時間は長くなります。10;}CreateMandelbrotSetBitmap();Invalidate();base.OnMouseDown(e);}}これだとそれっぽいものが描画されます。試行回数を30回から60回に増やすだけでこんなにもかわります。試行回数60回ただdouble型の範囲を超えてしまうとどうすることもできません。よろしければ記事の拡散をお願いします。鳩でも分かるC#管理人からのお願いできる仕事であれば請け負います。鳩でもわかるC#管理人はクラウドワークスに在宅ワーカーとして登録しています。お仕事の依頼もお待ちしております。仕事を依頼するコメントについてコメントで英語などの外国語でコメントをされる方がいますが、管理人は日本語以外はわからないので基本的に内容が理解できず、承認することもありません。それからへんな薬を売っているサイトやリンク先のサイトが存在しないというスパムコメントも多々あります。comments.そんななか日本語のコメントもいただけるようになりました。「○○という変数はどこで宣言されているのか?」「××というメソッドはどこにあるのか」「例外が発生する」「いっそのことソース丸ごとくれ」という質問ですが、管理人としては嬉しく思います。「自分が書いた記事は読まれているんだな」と。疑問点には可能な限り答えます。記事に問題があれば修正いたします。そのうえでお願いがあります。「匿名」という味も素っ気もない名前ではなく、捨てハンでいいのでなにかハンドルネームをつくってほしいと思います。管理人のモチベーションアップのためによろしければご支援お願いします。「C#で魔方陣をつくる」コメントをどうぞ返信をキャンセルする。2024年9月6日ブログやっています。メインはC#ですが、JavaScriptにも挑戦しています。ときどきPythonとPHPもあるかも。