.net」タグアーカイブ

C# でぱい

前回のコードを C# で書いてみようと何故か思った。

書いていて気がついたのだが C# は百桁程度の整数も扱えない。
そういえば C++ も扱えない、今まで int64 までしか使ったこともない。

あぁ GMP ってそのことだったんだ。
Python や Ruby の整数は桁数が無限なので気がつかなかった。
てゆーか無限に扱える意味ってようするに数学の世界だと。

多倍長整数っていうんだね。
ググると BigInteger というのが見つかった。

CodeProject: C# BigInteger Class. Free source code and programming help

まあよく解らないものは使って覚えるのが一番早い。
クラスなので普通に new したあとは整数のように扱えるはず。
落としてプロジェクトに含めてみる。

いきなり困った、べき乗 Math.Pow() は double しか扱えない。

いや、考えてみたら計算は Math でやらなきゃいけないわけではない。
自分で for ループさせても何も問題無い、ここまではすぐに思いついた。
でもそれをどう計算…つまらないことに詰まってしまったり。

なんとか百桁に成功したところで一万桁とかにすると例外スロー。

private const int maxLength = 70;

この数値が関係あるらしい、大きな桁にするときは増やして使う。
まあとりあえずそんなこんなで書いてみたコード。

using System;
using System.Diagnostics;

namespace pi1
{
    class Test
    {
        // System.Numeric.BigInteger はまだない
        BigInteger p, q;

        BigInteger expansion(int n)
        {
            BigInteger x, nn, c, s, k;
            x = new BigInteger(0);
            nn = new BigInteger(0);
            c = new BigInteger(0);
            s = new BigInteger(0);
            k = new BigInteger(0);
            x = (p * q) / n;
            nn = n * n;
            c = 1;
            s = x;
            k = 1;
            while (x > 0)
            {
                x = x / nn;
                k = k + 2;
                c = -c;
                s = s + c * (x / k);
            }
            return s;
        }

        public void pie()
        {
            Console.WriteLine("円周率を計算します。");
            Console.WriteLine("桁数を指定してください");
            int prsn = int.Parse(Console.ReadLine());
            p = new BigInteger(1);
            q = new BigInteger(1);

            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 1; i <= prsn; i++)
                p *= 10;
            for (int i = 1; i <= 10; i++)
                q *= 10;

            BigInteger y, u, v;
            y = new BigInteger(0);
            u = new BigInteger(0);
            v = new BigInteger(0);
            y = 4 * ( 12 * expansion(18) + 8 * expansion(57) - 5 * expansion(239) );
            y = y / q;
            u = y / p;
            v = y - u * p;
            sw.Stop();
            
            Console.WriteLine("{0}.{1}", u, v);
            Console.WriteLine("計算時間={0}", sw.ElapsedMilliseconds / 1000.0);
            Console.Read();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Test t = new Test();
            t.pie();
        }
    }
}

初期化の引数は BigInteger でもいいはずだけど怖いので int に。
あまり意味は無い。

cs_pi

IronPython より十倍速いわな、BigInteger が早いのだろうか。
それよりやはり .NET もコンパイルしたほうが早いということだろうけど。

とはいえ CPython にはボロ負けのまま…
せめてマルチスレッド化したほうが…意味があるかは置いておいて。
実用アプリじゃ全く問題無いことだし。

FFTとAGMによる円周率計算プログラム

C 言語は面倒くさいので上記のとかを試す。
百万桁でたったの 39 秒だもの、この差をどうこうしようとか思わないわ。

手元に IronPython 1.1 が残っていたので前回のコードを試す。
0.098 秒…あれ?二倍も速くなった、DLR ってもしかして絶望的に遅い?

IE 糞すぎる!

覚書ページの textarea → pre 化完了!
あーつかれた。

とりあえず SyntaxHighlighter v2 はなかなか良い。
それに pre なので wordpress で使うのも問題が無くなる。
textarea だと編集時に最初の閉じタグ以下が消滅していたもの。

しかし…

C# のコードをまるまる書いたページが IE で見れなくなった!
キチンと XAML も C# コードも pre で囲っているのに何故…
仮想マシンだけかな?もーやだ。

追記

原因判明、単なるオイラのミスだった。
IE って charset 指定をヘッダの一番上に書かないといけないのね…
そうしないとそれ以降の文字コードが解らずに読み込めないってことです。

でも何故か読み込めたページもあるんだよなぁ???
仕様が意味不明だ、やっぱり IE は糞すぎる!

BitmapEffect の負荷は高くない

せっかくなので BitmapEffect がどれだけ負荷が高いのか実験。
手持ちで一番巨大な 3072x2304px の画像を使って BlurBitmapEffect を掛けてみる。

2 ミリ秒…

BlurEffect にしてみる。

1 ミリ秒…

こりゃ差が全然解らないわけだわ。
この程度の BitmapEffect なら体感するような違いは無いってことなのね。
どういう使われ方を想定して BitmapEffect を無くす方向になったの?

解ったのは WPF で画像ビューアは一瞬で作れるということだけだった。
XAML に Image を配置して image1 という名前を付けたとして

private void Window_Drop(object sender, DragEventArgs e)
{
    string[] drags = e.Data.GetData(DataFormats.FileDrop) as string[];
    image1.Source = new BitmapImage(new Uri(drags[0]));
}

これだけ…後はプロパティを弄くるだけ。
せっかくだから何か作ろうか。

BitmapEffect プロパティが古い

SeeMe のソースを少し弄くって sp1 にしてから初コンパイルしたら…

「BitmapEffect プロパティが古い!」

と怒られた、なんやねんまったく。
てか俺って気がつくの遅!VS2008 を sp1 にしたのは何時や!

とにかく BitmapEffect は檄負荷だから近々無くなるので使うなということらしい。
BitmapEffect がハードウェア アクセラレーション化されたはずなんだけーがなぁ。

川西 裕幸のブログ : .NET Framework 3.5 SP1 Beta

しかたがない、更新しよう(そんな理由で…)

てゆーかオープンソースなんだから放置はマズイわな。

using System.Windows.Media.Effects;

img1.BitmapEffect = new BlurBitmapEffect();
↓
img1.Effect = new BlurEffect();

と Bitmap を取っ払って書き換えるだけでよさそうだが。
こうしないとアクセラレーションが使えないってことなのか?よく解らないけど。
負荷の違いは私の Athlon 64 x2 4200+ & AMD 690G のショボいマシンでも解らんぞ!

そういえば Drag and Drop での並べ替えをいいかげんに復活させなければ。
以前は全く見つからなかったがそろそろサンプルコードがネット上に上がっているかな?

CodeProject: Very Simple WPF Drag and Drop Sample without Win32 Calls. Free source code and programming help

CodeProject: Drag and Drop Items in a WPF ListView. Free source code and programming help

あぁ、これでなんとかなりそうだ。
ちなみに WindowsForm にあった listView1.GetItemAt みたいなメソッドは無い。
たかが ListViewItem 取得にこんな処理を自前で書けということらしい。

メソッドくらい用意してよまったく。
WPF がちっとも普及しない最大の理由はソレなんだから。

でも並べ替え自体は RemoveAt と Insert メソッドのみで簡単に終わる。
それもバインディングならもちろん元の ObservableCollection を並べ替えるだけ。
異様に簡単になったり異様に難しくなったり本当に面倒だなぁ WPF って奴は。

Spy++ で WPF

何を今頃の話。

Visual Studio Tools の Spy++ でちっとウインドウ検索していた。
これって UAC に引っかかるのよね、そんな大げさなアプリとも思えないけど。

ちっと思いついて SeeMe にファインダツールをドロップ。

えっ!WPF で作ったアプリには親ウインドも子ウインドも何も無いってこと???

意味不明の若い人へ説明すると…解説が難しいなぁコレ。
Win32 API で作ったウインドウはボタンやラベルも全部ウインドウである。
なのでメインウインドウにボタンがあったらボタンは子ウインドウということです。
ウインドウハンドルを持つモノは全部ウインドウ…ということで解るかな?

ソレが一つも無いということは全部ペンやブラシで描写しているのと同じコト。
ちなみに Y901 のコントローラボタンがそうやっているのでコレも当然ウインドウではない。

そういえば WPF は DirectX で描写していたんだっけ、これは「なるほど」という感じ。
.NET Framework が一番の親に居ると思っていたんだけど違っていた。
いったいドコまで今までと考え方を変えなければいけないのだろう?

もう一つ思いついて Explorer のリストビューにファインダツールをドロップ。

あれ?このリストビューって SysListView32 クラスってことなの???
解る人には解るとおり Win32 での「今までの ListView 」と同じっていうこと。
なのにこの描写、あぁワケワカになってきたぞ!

てっきり WPF と同じ方法で描写を実現かと思っていたが普通のウインドそのもの。
「何か」をやれば Win32 で作った ListView もこの「なめらか描写」に出来るってことみたい。
公開されなきゃどうにもならんが、なんか Vista って本当に難しい。