人に聞けない痔の悩み、これでスッキリ >>

通常、Perlで数値計算をする場合、有効桁数は15~16桁になってしまいます。
これを、32桁、64桁と精度を上げて計算する方法はないでしょうか。
現在の環境は、Perl 5.8です。

よろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

perl -MMath::BigFloat -e "print $Math::BigFloat::VERSION"


をコマンドラインから実行してみてそのバージョンが1.58(現時点での最新)
かどうかを確認し、最新であれば

>perl -MMath::BigFloat -e "print $Math::BigFloat::VERSION"
1.58
perl -MMath::BigFloat -e "my $x = Math::BigFloat->new(2); print $x->bsin(100);"
0.909297426825681695396019865911744842702254971447890268378973011530967301540783
5446201266889249593803

のように、Math::BigFloatクラスのメソッドが使えます。

最新のものでなければ、Windows 以外のOSなら cpan コマンドを、WindowsでActivePerlを使っているなら、
ppm コマンドを使って最新のものに更新してください。
このとき指定するのは Math::BigIntモジュールなのに注意してください。

>ppm-shell
ppm 4.01
Copyright (C) 2007 ActiveState Software Inc. All rights reserved.
ppm> search math-bigint
1: Math-BigInt v1.64
2: Math-BigInt v1.87
3: Math-BigInt v1.79
4: Math-BigInt-BitVect v1.11
5: Math-BigInt-Constant v1.04
6: Math-BigInt-FastCalc v0.15
7: Math-BigInt-FastCalc v0.10
8: Math-BigInt-GMP v1.24
9: Math-BigInt-GMP v1.19
10: Math-BigInt-Named v0.03
11: Math-BigInt-Pari v1.13
12: Math-BigInt-Random v0.03
13: Math-BigIntFast v6.0
ppm> install 2
Downloading Math-BigInt-1.87...done
Downloading Test-Simple-0.70...done
Unpacking Math-BigInt-1.87...done
Unpacking Test-Simple-0.70...done
Generating HTML for Math-BigInt-1.87...done
Generating HTML for Test-Simple-0.70...done
Updating files in site area...done
10 files installed
6 files updated
ppm> quit
    • good
    • 0
この回答へのお礼

ありがとうございます。無事、実行できました。

お礼日時:2007/09/26 10:08

どなたも回答されていないようなので・・・・。



Perlで有効桁数を上げて計算をするには、BigIntやBigFloatを使用します。
Zeal250さんが整数の演算を行いたいのか浮動小数点の演算で有効桁数を上げたいのかはわかりませんが、例として、整数演算の有効桁数を上げたいとすると、下記のようになります。

use Math::BigInt;

$big = Math::BigInt->new("1.23456789e+200");
$big *= $big;
print $big;

なお、お使いのPerlのバージョンが5.8であれば、

use biginit;
$big = 1.23456789e+200;
$big *= $big;
print $big;

としても、計算ができます。
Perl5.8以降では、Math::BigIntモジュールのラッパーがbiginitモジュールとして実装されているようです。
お試しください。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2007/09/26 10:09

use bignum;



パラメータ等はperldoc bignum で。
携帯端末からなのでとりあえずこれだけ。

ただ、好きなだけ精度をあげられる代わりに遅いです。

この回答への補足

ありがとうございます。

よろしければもう一点確認させて下さい。
"use bignum"を宣言した状態で、三角関数演算(sin)を使用すると
エラーストップしてしまいます。

コード:
use bignum;
sin(2);

エラーメッセージ:
"Operation 'sin':no method found, argument in overloaded package Math::BigInt at test.pl line 2"


"use bignum"を使わなければ、このエラーメッセージは発生しません。
use Math::BigInt記述していてもいなくても結果は変わりません。

bignumを使いつつ(有効桁数を上げつつ)、三角関数を計算できる方法
がありましたら教えて頂けないでしょうか。

よろしくお願いいたします。

補足日時:2007/09/15 16:58
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q数値かどうかの判定方法

$aに代入されているものが数値かどうかを判定するにはどのようにしたらよいのでしょうか?

Aベストアンサー

$a =~ /^[0-9]*$/
上記の場合、*は「直前のパターンの0回以上の繰り返し」の意味なので、0から9がなくても、つまり$aが空でもマッチしてしまいます。
なので、
$a =~ /^[0-9]+$/
としましょう。
(+は「直前のパターンの1回以上の繰り返し」)
また、0-9は\dで表すこともできるので
$a =~ /^\d+$/
と書くこともできます。

Q扱える数字の最大値

http://brassiere.jp/

ここのTOWNというゲームなのですが、
所持金が1e+20以上になるとエラーが出るようになりました。
これは扱える数字が1e+19までという事なのでしょうか。

Aベストアンサー

perl自体の話だと、、
・変数に入れるだけなら、文字列と数の区別は特にないので、メモリの許す限り。
・内部計算は基本的にCで言うところのdouble型なので、有効数字15桁程度、10の-308乗から10の308乗まで。
・多倍長演算モジュール使用で、もっと大きな有効桁数の計算も可能
です。

64bit整数の限界が丁度1e19~1e20なので、どこかで64bit整数に変換しているところがあって、そこがエラーになるのでしょう。

Qperl で 64ビットint を扱うには?

表題のとおりなんですけど、現在 C で long long を使わないとうまくいかないところがあるんですけど、同じ事を perl でやるにはどうすればいいのでしょうか? 修正の容易さなどからできれば perl でできればうれしいんですけど。

Aベストアンサー

(標準モジュールで)
use bigint;
とするだけで自動的に全ての演算子で多倍長整数が扱えるようになります。

QPerlで数値(小数点、負の数、指数を含む)チェックはできますか?

Perl(Version 5.005_03) で、値が数値(小数点、負の数、指数を含む)か否かを判定したいのですが、うまくいきません。何かよい方法はないでしょうか?
お願いします。
【環境】sun4-solaris, apache

Aベストアンサー

ああ、「?」の存在を忘れていました。
そうそう
if ($val =~ /^(-|\+|)\d+\.?\d*(E\+\d+|E\-\d+)?$/i){
だと、
-1.E+12
というのも引っかかります。
もちろんPerlとしては数値として扱われるので大丈夫ですが。
しかし、
-.5E+12
というのもPerl的には正しいはずなのに、こちらは引っかかりません。
-12E-4.5
-12E-.5
これらも正しいのにだめです。
どこまでのを求めますか?(^^;
if ($val =~ /^(-|\+)?(\d+\.?\d*|\d*\.?\d+)(E\+(\d+\.?\d*|\d*\.?\d+)|E\-(\d+\.?\d*|\d*\.?\d+))?$/i){
こうかもしれない・・・

Q複数ファイルの読み込みについて

perl初心者です。

あるディレクトリから拡張子がdataであるファイルを全て読み込みたいのですが、方法がわかりません。
cshで書くと
foreach arg (*.data)
コマンド $arg

のようになりますが、perlだと
foreach $arg (@arg){
コマンド $arg

となりますよね?
引数がリストなのでよくわかりません。
そもそもperlではできないのでしょうか?


それともう一点ですが、ファイルオープンするときに
foreachループの中で
open(FILE, "$arg");
とすることは可能ですか?
上の質問と組み合わせて全てのファイルを開いて作業を行いたいので。

説明が下手ですいません。補足しますのでよろしくお願いします。

Aベストアンサー

while(<*.data>)
{
## $_には、*.DATAなファイル名が格納されている。
open(F,"$_"); ##openする。
while(<F>)
{
##読み出された内容が$_に格納されている。
print $_; ##出力してみる。
}
}

というのが最短コーディングです。

QPerlで特定行から特定行までを抜き出したい

皆さんのお知恵をお貸し頂ければ幸いです。

Perlで以下のようなことをしたいと考えています。
例えば、次のようなテキストファイルがあったとします。

example.log
==================================
aaaa
hogehoge
test
okok
perl
script
==================================

上記ファイルを読み込んで、「hogehoge」から「perl」の間に挟まれた行だけ抜き出したいのです。
イメージとしては、読み込んだファイルを配列に入れて、一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

このような場合、どういう風にすればいいのでしょうか?
恐れ入りますが、ご教授頂ければ幸いです。

それでは、どうぞよろしくお願い致します。

Aベストアンサー

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $flag = 0 }
  elsif ($flag) { print "$data\n" }
}
close FH;

で、もっと略したいPerlな人だとこんな感じ。Perl独特の記法がふんだんに使われているので、勉強するには不向きかもしれませんが^^;

open FH, "example.log" or die $!;
while (<FH>) {
  print if /^hogehoge$/ .. /^perl$/ and !/^(?:hogehoge|perl)$/;
}
close FH;

※インデントに全角空白を使っているので、コピーする場合はタブなどに置換して下さい。

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $fl...続きを読む

Qファイルの行数取得

超初心者です。

いま、表計算的なスクリプトを記述しています。

あるファイルの行数を取得する関数ってあるんでしょうか?

ファイルに記述されている数値を足したり引いたりするのですが、forを使っての計算の際にファイルの行数が必要となりました。

Aベストアンサー

Perlにですね。ないはずです。
行数とはファイルに書かれた改行文字の個数ということなので
実際にファイルを全て読み込まないと行数はわかりません。
以下のように色々な方法があると思います

#### 単純な例
$a = 0;
open FD, "<file.txt" || die $!;
while (<FD>) {
$a++;
}
close FD;
print "行数:$a\n";

### 少しマニアックな方法
open FD, "<file.txt" || die $!;
@a = <FD>;
close FD;
print "行数:" . ($#a + 1) + "\n";


### 反則的方法(外部コマンド) ... UNIXの場合
print "行数:" . `wc -l file.txt` . "\n";

Qperl でエラー:Wide character in・・・とは何がいけないのでしょう?

エラーメッセージ:
Wide character in subroutine entry at C:/Perl64/lib/Encode.pm line 221.

この意味と対応策を教えてください。

Aベストアンサー

(昨今の)Perlには「utf8フラグ」なるものがあります。


通常、日本語の仮名や漢字は、複数の文字を組み合わせて表現しています。
例えば、「ア」という文字は
Shift_JISなら \x83\x41 という「2文字」
UTF-8なら \xE3\x82\xA2 という「3文字」
です。
この状態は、1バイト1バイトの文字が並んでいる状態なので、「バイト列」と呼ぶことにします。(バイナリと呼んだりもします)
ファイルには、この形で入っています。

この方式だと、「ア」が1文字として扱われずいろいろと不便です。
例えば、 Shift_JISのアに含まれる \x41 はASCIIコードでのAです。
ここで、s/A/B/ とすると、 AがBに書き変わるだけでなく、ア( \x83\x41)がィ (\x83\x42)に書き変わってしまいます。

そこで、これらを統一扱う「内部形式」というのを作りました。
それが「utf8フラグ付き文字列」です。

読み込み時は
 ファイルや文字列変数でのバイト列 → 復号( decode ) → 内部形式(utf8フラグ付き文字列)
書き出し時には
 内部形式 → 符号(encode) → ファイルや文字列変数でのバイト列
とすることで、内部形式では「ア」を一文字として扱うことができます。s/A/B/としてもアには影響ありません。

復号/符号 は入出力時に自動で行なうようにしたり、Encodeモジュールのdecode,encode等を使用して明示的に行なったりします。

この書き出しの時に、
 内部形式 → 符号(encode) → ファイルや文字列変数でのバイト列
としなければならないところを
 内部形式 → ファイルや文字列変数
と直接おこなってしまった場合、そんなことはできない、と発生するのが「 wide character 〜」の警告です。


対処法は、 上記のようにencodeすることです。
また、場合によっては decode を抑制して 最初からバイト列で扱う方が正しいこともあります。
具体的なことは、実際のコードとやろうとしていることがわかならないと答えられません。

(昨今の)Perlには「utf8フラグ」なるものがあります。


通常、日本語の仮名や漢字は、複数の文字を組み合わせて表現しています。
例えば、「ア」という文字は
Shift_JISなら \x83\x41 という「2文字」
UTF-8なら \xE3\x82\xA2 という「3文字」
です。
この状態は、1バイト1バイトの文字が並んでいる状態なので、「バイト列」と呼ぶことにします。(バイナリと呼んだりもします)
ファイルには、この形で入っています。

この方式だと、「ア」が1文字として扱われずいろいろと不便です。
例えば、 Shift_JISのアに...続きを読む

QCan't use string ("0") as an ARRAY ref の原因について

Perl 5.6を使っております。
Perlで原因不明なエラーに直面して困っております。
Can't use string ("0") as an ARRAY ref while "strict refs"
というエラーが発生しているのですが
これは良くあるミスとして何が原因でしょうか?

Aベストアンサー

No.2です。書き漏らしてましたが、エラーメッセージの内容がよくわからない時は

use diagnostics;

しましょう。

QFTPコマンドでディレクトリごとファイル移動できるコマンドはありますか?

タイトルどおりなのですが、FTPでファイルを転送する際に、サブフォルダを含むディレクトリごとファイル転送するコマンドはありますでしょうか。
ディレクトリの中にあるすべてのファイルを移動したいのですが、サブフォルダがたくさんあるので、わざわざディレクトリの場所へ移動してmputを繰り返すのはめんどうで仕方ありません。
よろしくお願いします。

Aベストアンサー

ご使用になるOS環境が書いてないのですが、Linux,BSD等ならncftpで、get -R dir。
Windowsならffftpを使えば良いと思います。


人気Q&Aランキング