Perlのブログ記事

 なんかMath::Roundがユーザーディレクトリにあっさりインストールできてしまった。動作も確認済み。インストールと言っても大げさなことじゃなく、Mathフォルダを作って中にRound.pmを入れただけ。それで、スクリプト側には

use lib "/カレントディレクトリまでの絶対パス/";
use Math::Round;
と記述する。パーミッションは適宜。
 まだPerlを学習し始めの頃に、このサーバのユーザーディレクトリでモジュールを動作させられないかと試行錯誤したことはあったけど、その時はできなかった記憶。サーバ側の設定が変わったのか、私のスキル(というほどのものじゃないけれど)があがったのか??
 ただ四捨五入問題についてはすでに自分で対症療法コードを書いてしまったので、特に問題なければこのまま行くつもり。たぶん、いちいちモジュールを呼び出すよりは速いと思うので。
 なんか、めちゃめちゃ拍子抜けかもしれない。

 昨日からCPANの検索機能がダウンしてるみたいなんだけど、もし同様に他のモジュール群も動作するようなら試してみたいものがなくもない。

 プログラミング(のまねごと)をやってると脳が糖分を欲するのか無性に甘いものが欲しくなるんだけど、昨今慣れてきたのかCGIスクリプトを書いていてもそこまで甘食じゃなくても耐えられるようになってきた。

| コメント(0) | トラックバック(0) |  

 「perlで小数を四捨五入」問題を深追いしてたらやめられないとまらない。

・小数の四捨五入の仕方
http://easycgi.xrea.jp/perltips/round.htm
 上記ページに載せられているスクリプトをコピペで動作検証すると、2.345を小数点第三位で四捨五入した場合2.34になります。つまり普通に間違ってます(perl5.8.9で確認)。intを実行した時点(手順2)で$nが内部的に無限小数になるようですが、手順2の次の行で$nをprintすると「見かけ上」補正されるのが罠。手順3の$qは無限小数化してしまっている。
 ちなみに、小数点以下を四捨五入するときによく使われるっぽい0.5足してintするという方法も、この事例に合わせてコード化した場合、int((2.345 * 100) + 0.5))/100とかすると、答えが2.34になります。むろん同じように間違ってます。
 sprintfがダメだからintでいいというわけではありません。

・perlで四捨五入>sprintf() による四捨五入は避けるべきでは
http://d.hatena.ne.jp/end0tknr/20080928/1222581535

・四捨五入でも int の使用は避けるべきでは。。。?
http://harapeko.asablo.jp/blog/2006/11/27/972082

 なんか調べていたらとちょっと怖くなる感じもあった。プロのプログラマっぽい人でも普通にsprintfや0.5足してintする方法を紹介している。事情をわかってて入門者用にわざと大雑把にやってるのかもしれないけど、なんかの計算で小数が混じってたらperlは当たり前のように四捨五入を間違うんだけど、ほんとにsprintfやintを紹介していいんだろうか。小数の四捨五入それ自体は小学4年生位で習うみたいで、大抵の人はできると思うが。
 perlが2進数変換にともなって四捨五入を間違う問題は、いずれにせよ、すでにある便利なモジュールを使うのが正しいってわけだけど、実は、このサーバではその便利なMath::Roundとやらは入ってないのであります。いやぁ、それで苦肉の策として、数値を文字列(リテラル)として扱うコードを書いて、モジュールもsprintfもintも使わずに小数を四捨五入してます。たぶんかなり筋の悪い方法ですが、他にあんまり思いつきませんでした。
 以下サブルーチンの形でサンプルを出してみました。よく言えば力技、悪く言えば泥縄式。うー!


※小数部分をperlで四捨五入するための泥縄式サンプル

sub DECIMAL_ROUND {
my $num=$_[0]; #処理対象の数
my $round_digit=3; #小数点以下第何位で四捨五入するか(1以上だがあまりに大きすぎるとエラー)
my $plus_minus = 0;

#マイナスの数値の場合の前処理
if ($num < 0) {
$num = abs $num;
$plus_minus = 1;
}

$num = $num * (10 ** $round_digit);#四捨五入する桁以上をすべて整数にする

if ($num =~ /^(\d+)\.\d+$/) {#まだ小数部分がある場合に文字列として切り捨て
$num = $1;
}

if ((length $num) == 1) {#四捨五入する桁しかない場合
if ($num >= 5) {
$num = 1;
}
else {
$num = 0;
}
}
else {#それ以外の場合
my $round_num = chop $num;

if ($round_num >= 5) {
$num++;
}
}

$round_digit--;#四捨五入後の小数点以下の桁数に変換(変数を節約してるだけ)
$num = $num / (10 ** $round_digit);#小数点の位置を元に戻す

#マイナスの数値の場合の後処理
if ($plus_minus == 1) {
$num *= -1;
}

return $num;
}

| コメント(0) | トラックバック(0) |  
URL/ID

2023/10/16
 Chromeの仕様変更に合わせてHTTPSに対応しました。

2023/05/17
 ファイル名に動画のタイトルを表示するようにしました(ファイル名に特殊な記号が含まれているとエディタ等で開けなくなる場合があるかもしれませんが、リネームしてください)。

2021/12/04
 Youtubeの仕様変更に対応しました。
 自動生成字幕のファイル名のasrは自動音声認識(Automatic Speech Recognition)の略です。
 年齢制限などで表示にログインが必要な動画には非対応です。
| コメント(24) | トラックバック(11) |  
【対応URL形式】
①http://law.e-gov.go.jp/cgi-bin/idxselect.cgi~
②http://law.e-gov.go.jp/htmldata/~

 このCGIは、総務省が運営する「法令データ提供システム」の法令データHTMLを、ローカル使用に適した形に補正します。上記フォームに対象URLを入力して「ダウンロード」を押せば、スクリプトがデータを取りに行って処理したものを出します。
 件サイトの法令データHTMLはオンラインかつフレームで利用することを前提として組まれており、ローカルにファイルとして落とすと使いづらくなります。本CGIはこれに対して補正処理を行っているわけですが、具体的には以下の三点について処理しています。
一.目次のハイパーリンクタグからフレーム用属性のtarget="data"を消除して、単純なページ内リンクにする
二.他の法令等を呼び出す引用リンクタグ内のURL表記を相対パスから絶対パスに変換する
三.保存するファイル名をタイトル名(法令名)にする
※条文内容についてはスクリプト処理上一切変更を加えていませんが特に同一性を保証するものではありません。※外部サイト(検索エンジンのキャッシュ、RSSリーダー,etc)からは動作しません。※総務省は法令データの二次利用を自由化しています
| コメント(0) | トラックバック(0) |  

今日の日付

月別 アーカイブ

※随時加筆修正する場合があります。

※コメント・サインイン用のOpenIDは、GoogleYahoo! JAPANmixiはてなlivedoor等のアカウントに、あらかじめ付属しているものがあります。

Powered by Movable Type 4.22-ja