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 を使用しているそうであるが,これらとの大きな違いは

  • 数値定数を全て Math::BigInt or 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

期待した通りの結果が得られる.

うーん.


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2007-06-07 (木) 05:08:50 (6191d)