窗口大小为0.1的概率频率分布增加错误的桶

时间:2016-07-16 09:10:42

标签: perl range

我没有使用相等的运算符来执行此操作,因为窗口大小的用户输入可能会有所不同。

print"Enter the window size";
my $p_win=<>;#window size can vary according to the user's requirement
chomp($p_win);

my $x=0;
my $y=$x+$p_win;
my $i=0;
my @count;
#initializing the value of the count for all the ranges as 0
while($x ne 1)
{
    $count[$i]=0;
print "$x>= p >$y\t$count[$i]=\n";<>;
    $x=$x+$p_win;
    $y=$y+$p_win;
    $i++;
}
$count[$i]=0;# count where the value of D is NA and E is 1
my $na=$i;  

open(F1,"new.txt");
my $flag=0;
my (@a,@b);
while(<F1>)
{
    if($flag == 0)
    {
        $flag++;#first line of the new.txt
    }
    else
    {
        chomp($_);
        my @a=split(/\t/,$_);
        $x=0;
        $y=$x+$p_win;
        for($i=0; $i<scalar(@count)-1; $i++)
        {
            if($a[3] eq 'NA')
            {
                $count[$na]++;                  
                $i=scalar(@count);
            }
            else
            {
                if($x le $a[4] && $a[4]<$y)
                {
                    $count[$i]++;               
                    $i=scalar(@count);
                }
                my $t=scalar(@count)-2;
                if($i== $t)
                {               
                    if($a[4] eq $y)
                    {
                        $count[$i]++;
                    }           
                }
            }
            $x=$x+$p_win;
            $y=$y+$p_win;
        }

    }
}

new.txt采用给定格式。将生成e的频率分布:

a   b   c   d   e
1   2   4   5   0.1
1   2   3   4   0.2
1   2   4   5   0.9
1   2   3   4   0
1   2   4   NA  1
1   2   3   4   0.2
1   2   4   5   0.3
1   2   3   4   0.9
1   2   4   5   0.8
1   2   3   4   0.7
1   2   4   5   0.6
1   2   3   4   0.5
1   2   4   5   0.4
1   2   3   4   0.2
1   2   4   5   0.1
1   2   3   4   1
1   2   4   5   0.9
1   2   3   4   0.8
1   2   4   NA  1
1   2   3   4   0.4
1   2   4   5   0.5
1   2   3   4   0.2
1   2   4   5   0.3
1   2   3   4   0.1

输出结果为:

0 >= p > 0.1    1
0.1 >= p > 0.2  3
0.2 >= p > 0.3  6#count of 0.3-0.4 is also added here
0.3 >= p > 0.4  0
0.4 >= p > 0.5  2
0.5 >= p > 0.6  2
0.6 >= p > 0.7  1
0.7 >= p > 0.8  1
0.8 >= p > 0.9  2
0.9 >= p >= 1   4
NA 1     2

1 个答案:

答案 0 :(得分:2)

首先,使用eqnelt等字符串比较器来比较数值总是一个坏主意。它使Perl将值转换为字符串并逐个比较字符,而不是直接比较数字。

此外,您永远不能比较浮点数的相等性,因为在英特尔浮点数中无法精确表示0.1之类的值。这尤其适用于值是一系列添加的结果,因为例如添加十个0.1的副本将导致每个值的十倍的错误

您可以允许任意误差范围,例如

if ( abs($x - $y) < 0.00001 ) { ... }

但那是笨拙和无意义的

到目前为止,使用这样的序列的最佳方法是将所有算法保持为整数格式。在我的回答中,我已经从使用窗口大小 $p_win更改为窗口数 $num_win,这始终是一个整数。然后,给定概率$i的数组索引$p仅为$i = int $p * $num_win

use strict;
use warnings 'all';

print "Enter the number of windows: ";
my $num_win = <>;

if ( $num_win and $num_win =~ /\S/ ) {
    chomp $num_win;
}
else {
    $num_win = 10;  # Default to ten windows
}

printf "\nCalculating for %d Windows\n", $num_win;

my @count;
$_ = 0 for @count[0 .. $num_win];

open my $fh, '<', 'new.txt' or die $!;

while ( <$fh> ) {

    next if $. == 1;
    next unless /\S/;

    my @fields = split;
    my $i;

    if ( $fields[3] eq 'NA' ) {
        $i = $#count;
    }
    else {
        $i = int $fields[4] * $num_win;
        --$i if $i == $#count;
    }

    ++$count[$i];
}

for my $i (0 .. $#count ) {

    if ( $i < $#count ) {
        printf "%.2f <= p < %.2f  count %d\n", $i/$num_win, ($i+1)/$num_win, $count[$i];
    }
    else {
        printf "%.2f (NA)         count %d\n", $i/$num_win, $count[$i];
    }
}

输出

Enter the number of windows: 
Calculating for 10 Windows
0.00 <= p < 0.10  count 1
0.10 <= p < 0.20  count 3
0.20 <= p < 0.30  count 4
0.30 <= p < 0.40  count 2
0.40 <= p < 0.50  count 2
0.50 <= p < 0.60  count 2
0.60 <= p < 0.70  count 1
0.70 <= p < 0.80  count 1
0.80 <= p < 0.90  count 2
0.90 <= p < 1.00  count 4
1.00 (NA)         count 2