投稿者「sasakima-nao」のアーカイブ

読めない UTF-8

IronPython URLs: WPF on IronPython: Windows and Dispatching

日本語は読めないようなのによくココなんて見つけたもんだ。
というか英語ページにこういうのは無いのだろうか?

まあ WPF=3D みたいな雰囲気ができあがってしまったし。

PyGtk のようにもっと普通に GUI 部品として使う発想があってもいいのに。
せっかく元々が .NET な IronPython なんだから抵抗も少ないのだし。
でも逆に Linux にて PyGtk を経験していないと思いつきもしないのかも。

Emerge Technology: Pythonで隠しファイルかどうかってどうやって確認するだっけ?

うっ!そういえばできない。
普通に win32file を import とか書いてあって少し心配なんだが。
下記モジュールを導入しないと存在しないんですけど。

SourceForge.net: Python for Windows extensions

PLATLIB\win32\lib\win32con.py で定数はほとんど定義済みなのが嬉しい。
しかし外部依存ファイルに頼るとアプリの配布はどうすんの?になるんだが。

それよりWindowsAPI を使うなら VC++ で作ったほうがケタ違いに楽なんだが。
API 関数も定義済みヘッダが揃っている、配布もランタイムのリンクをすれば一つですむ。
スクリプト言語のほうが生産効率が悪いなんてギャグにもならない。

やっぱり Windows で Python ってイマイチだ。
もうすぐ Ubuntu 9.04 が出るから Linux へ戻るとするか。

その前に

decode

少し前の行でも同じエラーになったんだが…
もちろん UTF-8 だ、適当なサイトで試したらなんともなかった。

まさかと思い秀丸でまったく同じ文字列をトレースしたら直った。
何故?Linux と Windows では吐く UTF-8 が違うのだろうか。

んでこの行は同じようにやっても直らない、もうわけがわからん。

UNICODE の解釈がおかしいみたいな。
中国語として扱われているとかするんかなぁ?
Opera はチョン語だったとか色々あるし…
単に私の理解不足だろうと思うけど解らないや。

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 ってもしかして絶望的に遅い?

ぱい

super pi を作ろう – ぴょぴょぴょ? – Linuxとかプログラミングの覚え書き –

というのを見つけた。
正直よく解らないけど(だから素人のままなんだ…)
super pi みたいなのを自作するのは面白そう、もっと勉強せねば。

とにかく Python でπの無限出力はどうすればいいのだろう?
スクリプト言語はこの手の計算は不得意だと解っているけどやってみたい。

math.pi では小数点以下 16 桁までしか出力してくれないし。

B. 浮動小数点演算、その問題と制限

ということで Web を探す。
とにかく例の一つでもないと私のような素人はさっぱり解らない。

情報処理 II, 第6回

簡単に見つかった…
早速 circleratio.py というのを落として実験。
エンコードが何故に latin-1 ? utf-8 に変更しておこう。

print はきちんと括弧でくくったのに例外出まくリング…

そういえば Python 3 って他にも沢山変わっていたんだっけか。

特集:もっと知りたいPython3000|gihyo.jp … 技術評論社

input() は eval(input()) にしないと文字列になるので書き換えて。
/ は // にしないと float になっちゃうので書き換えて。

#!/bin/env python
#-*- coding: utf-8 -*-
# 2007.4.9
#
# ガウスの公式による円周率の計算

from math import *  # 数学関数を使うためのまじない
from time import *  # 時間関数を使うためのまじない
from sys import *   # システム関数を使うためのまじない

# arctan(1/n) の小数展開
def expansion(n):
    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

print ('円周率を計算します。')
print ('桁数を指定してください。')
prsn = eval(input())

t0 = time()     # 開始時刻
p = 10**prsn
q = 10**10

y = 4 * ( 12 * expansion(18) + 8 * expansion(57) - 5 * expansion(239) )
y = y // q
u = y // p
v = y - u * p
t1 = time()     # 終了時刻

print ("%d.%d" % (u,v))
print ('計算時間 =', t1 - t0)
fin = stdin.readline()  # Enter キーで終了

メンドクセ!
40 行のコードでコレでは大きなプログラムはマジ大変だろうなぁ。

そういえば math,time,sys は IronPython にも組み込まれているはずだよなぁ。
やってみたら一行目を消さなきゃエンコードを認識しないかやはり。
Linux の IronPython は何故か imput() ができなのでパス。

pi

IronPython 遅っ!
コンマ付きの print もおかしいし、やはり普通の Python 代わりは無理だわ。

しかし実行中は見事にデュアルコア CPU の 50 %利用ってのが笑えるよ。
ちなみに AMD Athlon64 X2 4200+ と AMD 690G というショボい構成のまま。

picpu

十万桁に 89 秒も掛かった、百万桁なんて恐ろしくて出来ん。
つか、こういうのはやはり C 言語でやるべきだよと。

ctypes で WindowsAPI

Python には Windows の DLL に直接アクセスできるモジュールがあるようで。

14.14 ctypes — Pythonのための外部関数ライブラリ。

面白そうなので試してみる。
実験だから簡単なのにしたいなぁ。
MessaageBox 関数ならロードする関数は一つなのでコレでいこう。

14.14.1.2 ロードしたdllから関数にアクセスする

に書いてあるけど Windows の関数は Ansi 版と UNICODE 版がある。
当然 TCHAR マクロも使えない、これは VC++ がコンパイル時に変換しているから。

MessageBox 関数も例外ではない。
MessageBoxA と MessageBoxW にコンパイル時に振り分けされる。
幸いにも Python3.0 の文字列は UNICODE なので MessageBoxW を使う。

そして MessageBoxW は user32.dll にあります。
ということで。

#! /usr/bin/env python
# -*- coding: UTF-8 -*-

import ctypes

MB_OK = 0
MB_OKCANCEL = 0x00000001
IDOK = 1

dll = ctypes.windll.user32
res = dll.MessageBoxW(0, str(dll), "たいとる", MB_OKCANCEL)

if res == IDOK:
    dll.MessageBoxW(0, "OK を押しました", "りざると", MB_OK)
else:
    dll.MessageBoxW(0, "きゃんせるを押しました", "りざると", MB_OK)

mbox

うわぁコレでいけちゃうんだ。
MB_OK とかの定義は WindowsSDK の WinUser.h を見てちょ。

全部 DLL から呼び出せばウインドウもコントロールも作れるね。
でも定数を全部自分で定義せにゃいかんのが面倒そう…

えむえでぃた

とりあえず Windows での Python は EmEditor で行こうと思う。
一応こんな設定にしてみた。

emedit

Home キーでカーソルをインデントの先頭に行かせる。
Shift+Tab でインデント分カーソルを戻す。
という動作は秀丸ではできないっぽいんで。

PyScripter なんてのも見つけたけど普通のテキストエディタのほうがエエわ。
スクリプト言語を IDE で書くなんて馬鹿げていると思うようになったよ。
更に言語ごとに別の IDE だなんて何がしたいの?みたいな。

とりあえずコイツにはスニペットプラグインもあるしガンガン登録してしまえ!
と思ったけどこのスニペットって単語登録ができるだけっぽいな。
それも Tab キーで補完じゃなく選択して Enter なんだ、ガッカリ。

まあ EmEditor はアウトプットがあるから便利だ。
と思ったけど…

output

おもくそ文字化けしとるやないの。
コンソールなら普通に表示できるのになんやこれ、ガッカリ。

それとツールに Python と IronPython を登録。
これでボタンを選ぶだけでどちらも動作確認ができるぞと。
アウトプットが化けるから pythonw.exe でなく python.exe にしておくか…

Ruby も一応ツールに登録していたんだけど全く使わないので登録解除。
IronRuby なんてもう忘れられた子になっている、そんなのあったなぁ…

他に VL ゴシックにしたり読み書きは BOM 無し UTF-8 に指定したり。
なんか意地でも Ubuntu の gEdit に合わせようとしている自分が怖い。

しかし弄くれば弄くるほど Windows と Linux の文化の違いを感じるよ。
テキストエディタに求められているものが違いすぎ。

追記

アウトプットの文字化けは私の設定ミスだった…
出力エンコードを UTF-8 にしていた、システム規定でよかったのね。
江村さんごめんなさい。

それと Shift+Tab の動作だが Tab 分カーソルが戻るだけだった。
文字列を選択していない場合は逆インデントをやってくれない。
これは困る、逆インデントに BackSpace を4回叩くなんてやってられないよ。

しかたがないのでマクロを作る。

if (document.selection.IsEmpty) {
	document.selection.DeleteLeft(4);
} else {
	document.selection.UnIndent(1)
}

を作り Shift+Tab の割り付けをコッチに変更という強引なワザで。
これで範囲選択状態の動作は維持しながら未選択の場合は前方四文字削除だ。
というか gEdit と同じ動作。

問題はインデントの先頭で実行することしか考えていないことだったりする。