• 締切済み

perlで一定の範囲ごとにカウントさせる方法について教えてください。

perlで一定の範囲ごとにカウントさせる方法について教えてください。 例えば、data.txtに、-10≦n≦10の範囲で様々な数が入ったファイルがあるとして、 -10.0 ≦ x < -9.9 -9.9 ≦ x < -9.8 .... 9.8 ≦ x < 9.9 9.9 ≦ x ≦ 10.0 (←最後は≦のほうがいいですが、<でもOK) と0.1ごとに区切って、 その範囲に入る数をカウントしたいとき、 ifや+=を使って範囲を指定して、カウントアップさせる方法もありますが、 指定したい範囲の数が多いと、ifばかりをプログラム内に羅列するのは面倒です。 できれば以下のような結果が表示されるとうれしいのですが… 中間値 カウント数 -9.95 3 -9.85 6 ... すっきりした書き方はありませんか?よろしくお願いします。

みんなの回答

  • SaLeeFA
  • ベストアンサー率66% (6/9)
回答No.5

他の人の回答見てませんけども。 何に使うデータで、そのあとどのように、どの程度使うのかは分かりませんが。 テストはしてません。正規表現部分は都合に合う様に好きにして下さい。 ----------------------------------------------- @data; #全ての数値が入っている物とする。 foreach (@data){ { m/([0-9]+\.[0-9]?)/ } $count{"$1"}++; } ------------------------------------------------- 中間値とカウント数のの意味は分かりませんでしたが、 ハッシュのデータをごにょごにょしてカウント数から導き出せる数値は全部出せます。

すると、全ての回答が全文表示されます。
  • shiren2
  • ベストアンサー率47% (139/295)
回答No.4

テストは行っていませんので、バグがあるかもしれませんが…。 参考までにどうぞ。 インデントは全角スペースになっています。 #!/usr/bin/perl use strict; use POSIX; open(IN, "data.txt") or die; my %hash; while(<IN>){  # 2桁目以降の端数を切り上げ  my $n = &ceil($_*10)/10;  # インクリメント  $hash{$n}++; } print "中間値\tカウント数\n"; for(sort{ $a <=> $b } keys %hash){  # -10.0から-9.9(keyは-9.90)を、-9.95と表示  printf("%.2f\t%d\n", $_-0.05, $hash{$_}); }

すると、全ての回答が全文表示されます。
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

今回の条件(上限下限が決まっている。定間隔)だったら $val=( 読み込んだ値 ) だとして、 $minval = -10 ; # 最小値 $maxval = 10 ; # 最大値 $stepval = 10 ; # 0.1の逆数 if ( $val < $min ) { $level = 0 ; } elsif ( $val >= $maxval ) { $level= 199; # ≦10のための処理 }else{ $level =int(($val - $minval) * $stepval) ; #区間番号0~199 } $count[ $level ] += 1 ; 表示は for($i=0;$I<200;++$i){ $start = $minval + $i / $stepval ; $end = $minval + ($i+1) / $stepval ; $mid = ($start + $end)/2 ; printf "%5.2f %d\n", $mid, $count[$i]; }

すると、全ての回答が全文表示されます。
回答No.2

一定範囲ごとにカウントしたい場合、 一般的には大きい数字から比較していけばよいと思うのだけどそれじゃだめですか? 実験は面倒なので理論だけ。(未テストです) イメージ的には my @floor = ( -9.9 -9.8 -9.7 -9.6 ); # 比較したい数字を降順にしたもの my @count = () # カウントの結果 my $value = -9.75; # txtから読み取った数字 count_loop: for( my $N=0; $N<$#floor; $N++ ) { if( $floor[$N] <= $value ) { $count[$N] ++; last count_loop; } } テキストの中身が範囲内に収まっているのならこれで十分かなーとおもうけど 後は表示するときに、 増分の半分を $floorに足してあげれば中央値になるかなー?

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

たとえば sub check_inclusive_exclusive { my ($left, $right) = @_; sub { $left <= $_[0] && $_[0] < $right; }; } sub check_inclusive_inclusive { my ($left, $right) = @_; sub { $left <= $_[0] && $_[0] <= $right; }; } my @counts; for (-100 .. 98) { my $left = $_ / 10.0; my $right = ($_+1) / 10.0; my $mid = ($_+0.5) / 10.0; push @counts, +{ left => $left, right => $right, mid => $mid, check => check_inclusive_exclusive($left, $right) }; } push @counts, +{ left => 9.9, right => 10.0, mid => 9.95, check => check_inclusive_inclusive(9.9, 10.0) }; for my $count (@counts) { $count->{count} = 0; } open my $fh, '<', 'data.txt'; while (<$fh>) { for my $count (@counts) { ++$count->{count}, last if $count->{check}($_); } } とする手はあると思うけど, これでうれしいかどうかは知らん.

すると、全ての回答が全文表示されます。

関連するQ&A