読者です 読者をやめる 読者になる 読者になる

aokcub::Blog

/PIC|dsPIC|Perl|Terragen3|風景CG|CSS3/

Perlでやたら大きい数字扱うとき

Perl memo

今,Twitterの検索API叩いてヒットしたツィートをメール通知するような自分用スクリプト書き掛けてます.

その中で過去に取得したツィートを保存して, 次に検索した時はその最大status_idより新しいもののみ取得するようにしてるんだけど, その制限がうまく効かずハマりかけたのでメモ.

なんかAPIの仕様確認したら不要な処理だったけどPerl力上がったので残しておきます

use strict;
use warnings;
use Data::Dumper;

my $num = '270815800892465152'; # status_id 例
print Dumper $num; # => $VAR1 = '270815800892465152';

$num = $num + 1;   
print Dumper $num; # => $VAR1 = '2.70815800892465e+17';

!?

どうもPerlの有効桁数の問題とのこと. たまたま今回はstatus_idをSQLite DBにTEXT型で保存していたので, DBから取ってきたときは文字列になる.

そのstatus_idに対して「それより新しいツィート」を取るために+1したい. このとき数値として扱うわけなんだけど, 有効桁数(15,16桁)より大きい桁数を扱っているため, 正しく扱ってくれない.

これをAPI叩くときのパラメータに入れても, そりゃーちゃんとリミット掛けてくれませんね.

解決策

use bigint;

を使う.

use strict;
use warnings;
use bigint;
use Data::Dumper;

my $num = '270815800892465152'; # status_id 例
print Dumper $num; # => $VAR1 = '270815800892465152';

$num = $num + 1;
print Dumper $num;

こんな感じで格納されてるようです.

$VAR1 = bless( {
                 'value' => [
                              2465153,
                              1580089,
                              2708
                            ],
                 'sign' => '+'
               }, 'Math::BigInt' );

7桁ずつ分割されてる模様.

参考

有効桁数の大きな数値を計算する Math::BigInt Math::BigFloat (サンプルコードによるPerl入門さん)

perlで標準より大きい有効数字の整数、小数を扱う (うまい棒blogさん)

謝辞

@neko_gata_s++ (アドバイスありがとうございました)