よく使うサブルーチン

提供: dococo wiki
2016年1月3日 (日) 12:58時点におけるimported>Webmasterによる版
ナビゲーションに移動 検索に移動

個人的によく使うサブルーチンをまとめてみました

出典元

参考にした出典元です 中央値処理


サブルーチン

#!/usr/bin/perl

	use strict;
	use warnings;

#---------------------------------------------------------------------------------------------------------------------
	#緯度経度からメッシュ番号を算出するサブルーチン
	#パッケージ名を「lat_long_to_mesh」とする
	#lat_long_to_mesh::mesh($Longitude, $Latitude, $MESH_CODE)と呼ばれることで
	#経度/緯度/メッシュサイズをで入れると、指定されたメッシュ番号に変換して返す
	#メッシュサイズ引数(1=1km/2=500m/3=250m/4=125m/5=100m)
	
package lat_long_to_mesh;
	
sub mesh {
    	my($Longitude_out, $Latitude_out, $MESH_CODE) = @_;
    	#print $Longitude_out,"-",$Latitude_out,"-",$MESH_CODE,"\n";

					#-------------------------緯度経度→メッシュ番号算出----------------------------------------------
					# 1st mesh(latitude)
					#・緯度×60分÷40分=p 余りa p=第1次地域区画を示す数字の上2けた の計算
					#
					my $mesh_P = int($Latitude_out * 60 / 40);
					my $mesh_a = ($Latitude_out * 60) - ($mesh_P * 40) ;
					#print "一次メッシュ(P=$mesh_P a=$mesh_a)\n";
					# 2nd mesh(latitude)
					#・ a÷5分=q 余りb q=第2次地域区画を示す数字の上1けた の計算
					
					my $mesh_Q = int($mesh_a / 5);
					my $mesh_b = $mesh_a - ($mesh_Q * 5) ;
					#print "二次メッシュ(Q=$mesh_Q b=$mesh_b)\n";
					
					# 3tn mesh(latitude)
					#・b×60秒÷30秒=r 余りx r=第3次地域区画を示す数字の上1けた の計算
					
					my $mesh_R = int($mesh_b * 60 / 30);
					my $mesh_x = ($mesh_b * 60) - ($mesh_R * 30) ;
					#print "三次メッシュ(R=$mesh_R x=$mesh_x)\n";
					
					# 4tn mesh(latitude)
					#・x÷15秒=R2 余りx2 R2=第4次地域区画を示す数字の上1けた の計算
					
					my $mesh_R2 = int($mesh_x / 15);
					my $mesh_x2 = $mesh_x - ($mesh_R2 * 15) ;
					#print "四次メッシュ(R2=$mesh_R2 x2=$mesh_x2)\n";
					
					# 5th mesh(latitude)
					#・x2÷7.5秒=R3 余りx3 R3=第5次地域区画を示す数字の上1けた の計算
					
					my $mesh_R3 = int($mesh_x2 / 7.5);
					my $mesh_x3 = $mesh_x2 - ($mesh_R3 * 7.5) ;
					#print "五次メッシュ(R3=$mesh_R3 x3=$mesh_x3)\n";
					
					# 6rh mesh(latitude)
					#・ x2÷3.75秒=R3 余りx3 R3=第5次地域区画を示す数字の上1けた の計算
					
					my $mesh_R4 = int($mesh_x3 / 3.75);
					my $mesh_x4 = $mesh_x3 - ($mesh_R4 * 3.75) ;
					#print "六次メッシュ(R4=$mesh_R4 x4=$mesh_x4)\n";
					
					# 100m mesh(latitude)
					# 緯度差3秒
					#・x÷3秒=R5 余りx4 R4=100mメッシュを示す数字の上1けた の計算
					
					my $mesh_R5 = int($mesh_x / 3);
					my $mesh_x5 = $mesh_x - ($mesh_R2 * 3) ;
					#print "100mメッシュ(R5=$mesh_R2 x5=$mesh_x2)\n";
					
					# 1st mesh(longitude)
					#・経度-100度=s 余りc s=第1次地域区画を示す数字の下2けた の計算
					#
					my $mesh_S = int($Longitude_out - 100);
					my $mesh_c = $Longitude_out -100 - $mesh_S ;
					#print "一次メッシュ(S=$mesh_S c=$mesh_c)\n";
					
					
					# 2nd mesh(longitude)
					#・c×60分÷7分30秒=t 余りd t=第2次地域区画を示す数字の下1けた の計算
					#
					my $mesh_T = int($mesh_c * 60 / 7.5);
					my $mesh_d = ($mesh_c * 60) - ($mesh_T * 7.5) ;
					#print "二次メッシュ(T=$mesh_T d=$mesh_d)\n";
					
					# 3th mesh(longitude)
					#・d×60秒÷45秒=u 余りy u=第3次地域区画を示す数字の下1けた の計算
					#
					my $mesh_U = int($mesh_d * 60 / 45);
					my $mesh_y = ($mesh_d * 60) - ($mesh_U * 45) ;
					#print "三次メッシュ(U=$mesh_U y=$mesh_y)\n";
					
					# 4th mesh(longitude)
					# 経度差は22.5秒
					#・y÷22.5秒=u2 余りy2 u2=第4次地域区画を示す数字の下1けた の計算
					#
					my $mesh_u2 = int($mesh_y / 22.5);
					my $mesh_y2 = $mesh_y - ($mesh_u2 * 22.5) ;
					#print "四次メッシュ(u2=$mesh_u2 y2=$mesh_y2)\n";
					
					# 5th mesh(longitude)
					#・y2÷11.25秒=u3 余りy3 u3=第5次地域区画を示す数字の下1けた の計算
					#
					my $mesh_u3 = int($mesh_y2 / 11.25);
					my $mesh_y3 = $mesh_y2 - ($mesh_u3 * 11.25) ;
					#print "五次メッシュ(u3=$mesh_u3 y3=$mesh_y3)\n";
					
					# 6th mesh(longitude)
					#・y3÷5.625秒=u4 余りy4 u4=第6次地域区画を示す数字の下1けた の計算
					#
					my $mesh_u4 = int($mesh_y3 / 5.625);
					my $mesh_y4 = $mesh_y3 - ($mesh_u4 * 5.625) ;
					#print "六次メッシュ(u4=$mesh_u4 y4=$mesh_y4)\n";
					
					# 100m mesh(longitude)
					#・y÷4.5秒=u5 余りy5 u5=100mメッシュを示す数字の下1けた の計算
					#経度差は4.5秒
					my $mesh_u5 = int($mesh_y / 4.5);
					my $mesh_y5 = $mesh_y - ($mesh_u2 * 4.5) ;
					#print "100mメッシュ(u5=$mesh_u2 y5=$mesh_y2)\n";
					
					#-------------組み立て-----------
					my $mesh1 = $mesh_P * 100 + $mesh_S;
					my $mesh2 = $mesh_Q *  10 + $mesh_T;
					my $mesh3 = $mesh_R *  10 + $mesh_U;
					my $mesh4 = oct('0b'.$mesh_R2.$mesh_u2) + 1;
					my $mesh5 = oct('0b'.$mesh_R3.$mesh_u3) + 1;
					my $mesh6 = oct('0b'.$mesh_R4.$mesh_u4) + 1;
					
					my $mesh_code_out = 0;
					
					if ($MESH_CODE == 1){$mesh_code_out = sprintf("%04d%02d%02d", $mesh1, $mesh2, $mesh3);} #1kmメッシュ計算
					elsif ($MESH_CODE == 2){$mesh_code_out = sprintf("%04d%02d%02d%01d", $mesh1, $mesh2, $mesh3, $mesh4);}#500mメッシュ計算
					elsif ($MESH_CODE == 3){$mesh_code_out = sprintf("%04d%02d%02d%01d%01d", $mesh1, $mesh2, $mesh3, $mesh4, $mesh5);}#250mメッシュ計算
					elsif ($MESH_CODE == 4){$mesh_code_out = sprintf("%04d%02d%02d%01d%01d%01d", $mesh1, $mesh2, $mesh3, $mesh4, $mesh5, $mesh6);}#125mメッシュ計算
					elsif ($MESH_CODE == 5){$mesh_code_out = sprintf("%04d%02d%02d%01d%01d", $mesh1, $mesh2, $mesh3, $mesh_R5, $mesh_u5);} #100mメッシュ計算
    	return $mesh_code_out;
}
	
#---------------------------------------------------------------------------------------------------------------------
	#メッシュ番号から中心緯度経度を算出するプログラム
 	#出力は三次/四次/五次/六次まで

sub mesh2lat_long{
	my($sample_data) = @_;

 	my $MESH_No = 0;#何次メッシュかを得る
 	
 	#メッシュの文字列の長さを得る
 	my $MESH_Length = length($sample_data);
	
	if($MESH_Length == 8){$MESH_No = 3}#三次メッシュ(1km)
	elsif ($MESH_Length == 9){$MESH_No = 4}#四次メッシュ(500m)
	elsif ($MESH_Length == 10){$MESH_No = 5}#五次メッシュ(250m)
	elsif ($MESH_Length == 11){$MESH_No = 6}#六次メッシュ(125m)
	
	#一次メッシュ算出
	my $MESH_01_Lat  = substr($sample_data,0,2) / 1.5;	#単位(度)
	my $MESH_01_Long = substr($sample_data,2,2) + 100;	#単位(度)

	#二次メッシュ算出
	my $MESH_02_Lat  = substr($sample_data,4,1) * 5;	#単位(分)
	my $MESH_02_Long = substr($sample_data,5,1) * 7.5;	#単位(分)
	#print $MESH_02_Long,"  ";
	#三次メッシュ算出
	my $MESH_03_Lat  = substr($sample_data,6,1) * 30 + 15;	#単位(秒)
	my $MESH_03_Long = substr($sample_data,7,1) * 45 + 22.5;#単位(秒)
	
	#四次メッシュ算出
	#算出が四次より大きければ処理する
	#編集初期化
	my $MESH_04_Lat  =0;
	my $MESH_04_Long =0;
	
	if ($MESH_No >= 4){
						if(substr($sample_data,8,1) == 1)
						{
						$MESH_04_Lat  = -7.5;
						$MESH_04_Long = -11.25;
						}
						elsif(substr($sample_data,8,1) == 2)
						{
						$MESH_04_Lat  = -7.5;
						$MESH_04_Long = 11.25;
						}
						elsif(substr($sample_data,8,1) == 3)
						{
						$MESH_04_Lat  = +7.5;
						$MESH_04_Long = -11.25;
						}
						elsif(substr($sample_data,8,1) == 4)
						{
						$MESH_04_Lat  = +7.5;
						$MESH_04_Long = +11.25;
						}
					}
	#五次メッシュ算出
	#算出が五次より大きければ処理する
	#編集初期化
	my $MESH_05_Lat  =0;
	my $MESH_05_Long =0;
	if ($MESH_No >= 5){
						if(substr($sample_data,9,1) == 1)
						{
						$MESH_05_Lat  = -7.5 / 2;
						$MESH_05_Long = -11.25 / 2;
						}
						elsif(substr($sample_data,9,1) == 2)
						{
						$MESH_05_Lat  = -7.5 / 2;
						$MESH_05_Long = 11.25 / 2;
						}
						elsif(substr($sample_data,9,1) == 3)
						{
						$MESH_05_Lat  = +7.5 / 2;
						$MESH_05_Long = -11.25 / 2;
						}
						elsif(substr($sample_data,9,1) == 4)
						{
						$MESH_05_Lat  = +7.5 / 2;
						$MESH_05_Long = +11.25 / 2;
						}
					}
	#六次メッシュ算出
	#算出が六次より大きければ処理する
	#編集初期化
	my $MESH_06_Lat  =0;
	my $MESH_06_Long =0;
	if ($MESH_No >= 6){
						if(substr($sample_data,10,1) == 1)
						{
						$MESH_06_Lat  = -7.5 / 4;
						$MESH_06_Long = -11.25 / 4;
						}
						elsif(substr($sample_data,10,1) == 2)
						{
						$MESH_06_Lat  = -7.5 / 4;
						$MESH_06_Long = 11.25 / 4;
						}
						elsif(substr($sample_data,10,1) == 3)
						{
						$MESH_06_Lat  = +7.5 / 4;
						$MESH_06_Long = -11.25 / 4;
						}
						elsif(substr($sample_data,10,1) == 4)
						{
						$MESH_06_Lat  = +7.5 / 4;
						$MESH_06_Long = +11.25 / 4;
						}
					}
#--------------------------------------------------------------------------
	#秒の積算
	my $Lat_Sec  = $MESH_03_Lat  + $MESH_04_Lat  + $MESH_05_Lat  + $MESH_06_Lat;
	my $Long_Sec = $MESH_03_Long + $MESH_04_Long + $MESH_05_Long + $MESH_06_Long;
	
	#print "秒の算出:(MESH_03)$MESH_03_Lat(MESH_04)$MESH_04_Lat(MESH_05)$MESH_05_Lat(MESH_06)$MESH_06_Lat\n";
	#print "秒の算出:(MESH_03)$MESH_03_Long(MESH_04)$MESH_04_Long(MESH_05)$MESH_05_Long(MESH_06)$MESH_06_Long\n";
	#print "\n";
	
	#この時点の時分秒
	#print "Lat :$MESH_01_Lat(度)$MESH_02_Lat(分)$Lat_Sec(秒)\n";
	#print "Long:$MESH_01_Long(度)$MESH_02_Long(分)$Long_Sec(秒)\n";
	
	#秒が60秒を超えたら分に加算
	$MESH_02_Lat = $MESH_02_Lat + int($Lat_Sec/60);
	$Lat_Sec = $Lat_Sec-int($Lat_Sec/60)*60;

	$MESH_02_Long = $MESH_02_Long + int($Long_Sec/60);
	$Long_Sec = $Long_Sec-int($Long_Sec/60)*60;
	
	#print "Lat :$MESH_01_Lat(度)$MESH_02_Lat(分)$Lat_Sec(秒)\n";
	#print "Long:$MESH_01_Long(度)$MESH_02_Long(分)$Long_Sec(秒)\n";

	#分が60分を超えたら度に加算
	$MESH_01_Lat = $MESH_01_Lat + int($MESH_02_Lat/60);
	$MESH_02_Lat = $MESH_02_Lat - int($MESH_02_Lat/60)*60;
	
	$MESH_01_Long = $MESH_01_Long + int($MESH_02_Long/60);
	$MESH_02_Long = $MESH_02_Long - int($MESH_02_Long/60)*60;
	
	#print "Lat :$MESH_01_Lat(度)$MESH_02_Lat(分)$Lat_Sec(秒)\n";
	#print "Long:$MESH_01_Long(度)$MESH_02_Long(分)$Long_Sec(秒)\n";

	#緯度経度10進数計算
	my $MESH_Lat  = $MESH_01_Lat  + ($MESH_02_Lat  / 60) + ($Lat_Sec  / 60 /60);
	my $MESH_Long = $MESH_01_Long + ($MESH_02_Long / 60) + ($Long_Sec / 60 /60);

	#答え
	#print "Lat=",$MESH_Lat," Long=",$MESH_Long,"\n";
	return ($MESH_Lat,$MESH_Long);
}

#---------------------------------------------------------------------------------------------------------------------
#モジュールがインストールしていなくても平均/中央/最大/最小を算出するためのサブルーチン

#---------------平均値算出----------------------
sub mean{
	my $n=@_;
	my $mean=0;
	foreach my $i (@_)
		{
		$mean+=$i/$n;
		}
	return($mean);
}

#---------------最大値値算出----------------------
sub max{
	my @nums = @_;
  	my $max_num;
		for my $num (@nums) {
			if (!defined $max_num) {
			$max_num = $num;
			}
			else{
				if ($num > $max_num) {
				$max_num = $num;
				}
			}
		}
	return $max_num;
}

#---------------最小値算出----------------------
sub min{
	my @nums = @_;
	  my $min_num;
		for my $num (@nums) {
		    if (!defined $min_num){
    		  $min_num = $num;
   			}
    		else {
      				if ($num < $min_num){
        			$min_num = $num;
      			}
    		}
  		}
	return $min_num;
}

#---------------中央値値算出----------------------
sub median{

        my @list=sort{$a<=>$b}@_; #昇順にソート
        
        my $n=@_; #データの個数
                
        if($n%2==0){ #データの個数が偶数の場合
                my $x1=$n/2;
                my $x2=$n/2+1;
                my $median_g=($list[$x1-1]+$list[$x2-1])*0.5;
                #print "median=$median_g \n";
                return($median_g);
        }else{ #データの個数が奇数の場合
                my $x=$n/2;
                my $median_k=$list[$x];
                #print "median=$median_k \n";
                return($median_k);
        }
}


1;