Under the Bridge

a Picture of the Late Him

MTで乱数を発生させる(ダイジェスト)

2008年12月19日 00:13 | Writer: yoshi | 記事本文 | コメント(0) | トラックバック(0)

色んな方法がある。大きく分けると3種類。

乱数を用いる用途としては、色々考えられる。MTのデフォルトにはその機能がない。

JavaScriptを用いる

JavaScriptで乱数を得るときは以下のようなコードでいい。

ただしサーバーサイドでなんかの処理(テンプレートの処理分岐など)を行いたい場合には、使えない場合が多い。使途は狭いか?

MT4.1で乱数を取得したい場合
<MTSetVarBlock name="RndValue">
<SCRIPT language="JavaScript">
<!--
document.write(Math.floor(Math.random() * 10));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="RndValue">

プラグインを用いる

個人的にはこれが一番使いやすいと思う。再構築を行うとき、ひとつひとつ違う値が得られるわけだ。以下はプラグインのコード。

MT4:MTの変数演算をプラグインで拡張
package MT::Plugin::CalcExp;
use strict;
use MT;
use MT::Plugin;
use base qw(MT::Plugin);
use POSIX;

my $plugin = new MT::Plugin::CalcExp({
    id => "CalcExp",
    key => "CalcExp",
    name => "CalcExp",
    version => '0.1',
    description => "<__trans phrase=\"The Calculation Value(Expand) \">",
    author_name => "apstar",
    author_link => "http://www.mtde.info/",
});
MT->add_plugin($plugin);

sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        'tags' => {
            'function' => {
                'CalcExp' => \&_hdlr_getvalue,
            },
        },
    });
}

sub _hdlr_getvalue {
    my($ctx, $args) = @_;
    my $op = $args->{op};
    my $base = $args->{base};
    my $palam = $args->{palam};
    use constant PI => 3.14159265358979;
    
    if (('+' eq $op) || ('add' eq $op)) {
        return $base + $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif (('-' eq $op) || ('sub' eq $op)) {
        return $base - $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif (('*' eq $op) || ('mul' eq $op)) {
        return $base * $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif (('/' eq $op) || ('div' eq $op)) {
        return $base / $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif (('%' eq $op) || ('mod' eq $op)) {
        # Perl % is integer only
        $base = int($base);
        $palam = int($palam);
        return $ctx->error(MT->translate('Division by zero.'))
            if $palam == 0;
        return $base % $palam  if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif (('++' eq $op) || ('inc' eq $op)) {
        return ++$base if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif (('--' eq $op) || ('dec' eq $op)) {
        return --$base  if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif (('&' eq $op) || ('join' eq $op)) {
        return $base . $palam;
    }
    elsif ('zero' eq $op) {
        return sprintf("%0".$palam."d", $base);
    }
    elsif ('rand' eq $op)  {
        return $base + int(rand($palam))+1 if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('int' eq $op) {
        return int($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('round' eq $op) {
        return round($base, $palam) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('floor' eq $op) {
        return floor($base) if defined $base && $base =~ m/^\-?[\d\.]+$/; #by POSIX
    }
    elsif ('ceil' eq $op) {
        return ceil($base) if defined $base && $base =~ m/^\-?[\d\.]+$/; #by POSIX
    }
    elsif ('sin' eq $op) {
        return sin($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('cos' eq $op) {
        return cos($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('tan' eq $op) {
        return sin($base)/cos($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('deg2rad' eq $op) {
        return ($base / 180) * PI if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('rad2deg' eq $op) {
        return ($base / PI) * 180 if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('log' eq $op) {
        return log($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('pow' eq $op) {
        return ($base ** $palam) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }
    elsif ('sqrt' eq $op) {
        return sqrt($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
    }

    return $base;
}

sub round {
    my $val = shift;
    my $col = shift;
    my $r = 10 ** $col;
    my $a = ($val > 0) ? 0.5 : -0.5;
    return int($val * $r + $a) / $r;
}

1;

ダウンロードは以下から。

http://www.apstars.com/blog/download/calcexp.zip

使い方は以下。

http://www.apstars.com/blog/215/mt41mtcalcexp.php

MTのコードのみで...!

線形合同法による、MTタグでの乱数の取得のやり方。とくに難しいことはない。そのまんまMTMLなコードで実現できる。


<MTIgnore>線形合同法による乱数発生</MTIgnore>
<MTSetVarTemplate name="RndValGet">
<MTSetVarBlock name="tmp"><MTDate format="%S"></MTSetVarBlock>
<MTSetVar name="tmp" value="3" op="*">
<MTSetVar name="tmp" value="5" op="+">
<MTSetVar name="tmp" value="13" op="%">
<MTGetVar name="tmp">
</MTSetVarTemplate>

<MTGetVar name="RndValGet">

これを最初にMTMLコードで実現したのは、わたしの知る限りでは、現在はシックス・アパートに所属するaklaswadさんである。

http://blog.aklaswad.com/2008/000409.html

書き方がな...tmp演算にtmp変数のそのものを使うという、いかにもプログラムな使い方を覚えんと、パニックになるかもしれんかもしれんが知らん。tmp=tmp+5みたいな記述だったら=の右辺が先に計算されるんだよ。

初回にtmpへシステム時間の秒を入れている点が、ポイントか。再構築の瞬間に多数の乱数を得たいときには、もしかすると(というか必ず)プラグイン版のほうがいい結果を返す。

しかしながら、乱数の精度が低くていい、ちょっとした用途、であれば、十分使える。

トラックバック(0)

このブログ記事を参照しているブログ一覧: MTで乱数を発生させる(ダイジェスト)

このブログ記事に対するトラックバックURL:

コメントする






Categories
Entries
Feed
スポンサードリンク

parts

フィードメーター - Under the Bridge

あわせて読みたい

なかのひと

2008 yoshi(apstar)