perl の bignum †最近,時刻やストレージの容量など,32 bit over の整数を扱わざるをえない機会が多くなってきている. もちろん,( 32 bit CPU 上での ) 素の perl でも 2**32 を越える整数を扱うことはできるが,内部的には浮動小数点で保持しているはずであり,何かの機会にひょっこり誤差が出てきそうで気味が悪い. こういうときに多桁整数演算用のパッケージ Math::BitInt がある. が,これは純粋に perl クラスで実装されており,単純に足し算するだけでも #!/usr/bin/perl use Math::BigInt; $a = Math::BigInt->new ( '1' ); # $a = 1; $b = Math::BigInt->new ( '2' ); # $b = 2; $a->badd( $b ); # $a += $b; printf "%s\n", $a->bstr(); のような表記になり,ちょっと使いづらい. あと,bignum というクラス(?)もある. #!/usr/bin/perl use bignum; printf "%s\n", 1+2; 内部的には Math::BigInt と Math::BigFloat を使用しているそうであるが,これらとの大きな違いは
というわけで,プログラムの先頭に use bignum; と宣言するだけで,今までのプログラムが多桁演算対応に早変わりしてくれる. もちろん,演算速度は犠牲になるが,それは多桁演算とのトレードオフというものである. が,この bignum,妙な癖があるようで #!/usr/bin/perl package Foo; use bignum; sub new { my $class = shift; my $self = {}; my %param = @_; $self->{name} = $param{name}; bless $self, $class; } sub set { my $self = shift; my %kv = @_; while ( my ( $k, $v ) = each %kv ) { $self->{hash}->{$k} = $v; } 1; } sub show { my $self = shift; my $kv = $self->{hash}; printf "--- %s ---\n", $self->{name}; my %kloop = %$kv; while ( my ( $k, $v ) = each %kloop ) { $v = 'UNDEF' if !defined $v; print "$k => $v\n"; } 1; } sub DESTROY { my $self = shift; show ( $self ); 1; } 1; #--- $foo = Foo->new( name => 'explicit' ); $foo->set ( 1 => 2, 3 => 4, 5 => 6 ); $foo->show(); undef $foo; $foo = Foo->new( name => 'implicit' ); $foo->set ( 1 => 2, 3 => 4, 5 => 6 ); $foo->show(); exit; このプログラムを実行してみると… --- explicit --- 1 => 2 3 => 4 5 => 6 --- explicit --- 1 => 2 3 => 4 5 => 6 --- implicit --- 1 => 2 3 => 4 5 => 6 --- implicit --- 1 => UNDEF 3 => 4 5 => 6 exit より後では,インスタンスが一部消滅してしまうらしい. use bignum; の行をコメントアウトして実行すると,もちろん --- explicit --- 1 => 2 3 => 4 5 => 6 --- explicit --- 1 => 2 3 => 4 5 => 6 --- implicit --- 1 => 2 3 => 4 5 => 6 --- implicit --- 1 => 2 3 => 4 5 => 6 期待した通りの結果が得られる. うーん. |