[Rio-pm] Chaves de hash

thiagoglauco em ticursos.net thiagoglauco em ticursos.net
Quinta Novembro 29 13:43:54 PST 2012


Seu primeiro erro é o operador and. No documento perlop: $ perldoc 
perlop você vai descobrir o seguinte:

  " Logical And
      Binary "and" returns the logical conjunction of the two
      surrounding expressions.  It's equivalent to && except for
      the very low precedence.  This means that it short-circuits:
      i.e., the right expression is evaluated only if the left
      expression is true.
[...]
   C-style Logical And
      Binary "&&" performs a short-circuit logical AND operation.
      That is, if the left operand is false, the right operand is
      not even evaluated.  Scalar or list context propagates down
      to the right operand if it is evaluated."

Logo, seu código

if($keys >= $min and $keys <= $max){

deveria ser if($keys >= $min && $keys <= $max){

A segunda coisa é o seu range. Não sei a precisão que seu código 
precisa. Veja isso:

  $ perl -E '
if (-30.00000000000000001 >= -30 ){
say "-30.00000000000000001 is equal -30? Really";}
else {
say "Floating Point is not true real"};'
-30.00000000000000001 is equal -30? Really
  $


Eu faria algo como:

if($keys > $min and $keys < $max)

e, usaria, por exemplo -30.000001 como min e -20.000001 como max, por 
exemplo, para contornar o ponto flutuante, ou usaria um módulo 
matemático, como o Math::BigFloat.

http://perldoc.perl.org/Math/BigFloat.html

Eu nunca usei em algo que fosse crítico, mas me parece bem sólida e 
segura.


Em 2012-11-29 18:46, Aureliano Guedes escreveu:
> Renato, fiquei sem entender, no meu caso não esta fazendo so um loop?
> E qual a diferença entre usar um hash %h ou tranformar $h em um 
> hash??
> Desculpe as perguntas é que não faço nenhum curso ligado a computação
> logo as vezes fico "boiando".
>
> Thiago, segue o script caso tenha também algo a modificar/acrescentar
> a nível das minhas péssimas práticas.
>
> use warnings;
> use strict;
> use Path::Class;
>
> #Guardar os valores em um hash acessado pelo valor do mfe
> sub h_energy{
>  my $data = shift;
>  my $file = file($data)->openr();
>  my %hmfe = ();
>  my $mirna;
>  my $record;
>
>  while (my $linha = <$file>) {
>  if ( $linha =~ m{target:.*} ) {
>  $record = $linha . $record if ($record);
>  $hmfe{$mirna} = $record if ($mirna);
>  $mirna = $+{mirna};
>  $record = q() if ($record);
>  }
>  elsif ($linha =~ m{mfe:s+(S+)s+kcal/mol}){
>  $mirna = $1;
>  $record .= $linha;
>  }
>  else {
>  $record .= $linha;
>  }
>  }
>  return %hmfe;
> }
>
> sub termofilter{
>  my ($data, $min, $max) = @_;
>  my %d = h_energy($data);
>  foreach my $keys (keys %d){
>  if($keys >= $min and $keys <= $max){
>  print $keys . "n";
>  }
>  }
> }
> termofilter("hybrid.txt", "-30", "-20");
>
>> Date: Thu, 29 Nov 2012 17:27:15 -0200
>> From: thiagoglauco em ticursos.net
>> To: rio-pm em pm.org
>> Subject: Re: [Rio-pm] Chaves de hash
>>
>> Onde estou agora o firewall bloqueia o pastebin. Pela sua 
>> explicação,
>> verificar por regex seria uma solução segura. O número sera 
>> convertido
>> para um string e, se a sua regex prevê uma margem segura para a
>> imprecisão do ponto flutuante na sua aplicação, funciona sem 
>> problemas.
>>
>> Em 2012-11-29 16:59, Aureliano Guedes escreveu:
>> > Nossa, aqui virou uma arena de ideias, da para aprender muita 
>> coisa
>> > so lendo.
>> >
>> > O problema é o seguinte, eu tenho uma lista nesse formato:
>> >
>> > target: 01010101
>> > length: 581
>> > miRNA : hsa-miR-15a
>> > length: 22
>> >
>> > mfe: -24.4 kcal/mol
>> > p-value: 0.334111
>> >
>> > position 244
>> > target 5' C UCUCCUGUGGUCUCU G U 3'
>> > CACA GACCA GUGCUGUU
>> > GUGU UUGGU CACGACGA
>> > miRNA 3' AAUA U 5'
>> >
>> > Conforme este arquivo http://pastebin.com/9v6WFUT7
>> >
>> > Eu quero filtrar essa lista de acordo com o valor de mfe.
>> >
>> > Exemplo, se mfe for menor que -30 e maior que -20 esta dentro.
>> >
>> > Logo fiz da seguinte forma: http://pastebin.com/Dnhv0Zya
>> >
>> > Funcionou, o problema era sono. Não percebi que a regex estava
>> > pegando um espaço.
>> >
>> > Quanto a usar reais como chave de hash, se eu tiver dois reais 
>> iguais
>> > poderá ser um problema para acessar os valores,
>> > mas em toda regra existe sua exceção.
>> >
>> > No meu caso, o que me importa é que mfe esteja no intervalo
>> > determinado.
>> >
>> > Caso descordem seria uma honra ler a explicação de qualquer um de
>> > vocês.
>> >
>> >> Date: Thu, 29 Nov 2012 16:44:50 -0200
>> >> From: thiagoglauco em ticursos.net
>> >> To: rio-pm em pm.org
>> >> Subject: Re: [Rio-pm] Chaves de hash
>> >>
>> >> Um exemplo mais preciso:
>> >>
>> >> $ uname -a
>> >> SunOS cg01spo 5.10 Generic_138888-03 sun4v sparc
>> >> SUNW,SPARC-Enterprise-T5120
>> >>
>> >> $ perl -E '
>> >> if (0.2 > 0.19999999999999997){
>> >> say "0.2 is greater than 0.19999999999999997";}
>> >> else {
>> >> say "Floating Point is not true real"};'
>> >> 0.2 is greater than 0.19999999999999997
>> >> $
>> >>
>> >> $ perl -E '
>> >> if (0.2 > 0.19999999999999998){
>> >> say "0.2 is greater than 0.19999999999999998";}
>> >> else {
>> >> say "Floating Point is not true real"};'
>> >> Floating Point is not true real
>> >> $
>> >>
>> >> Por que é importante saber essas coisas?
>> >> http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html
>> >>
>> >>
>> >>
>> >>
>> >>
>> >>
>> >> Em 2012-11-29 15:13, thiagoglauco em ticursos.net escreveu:
>> >> >> Não se compara reais por igualdade.
>> >> > Se você tem erro na igualdade, terá nas outras comparações se a
>> >> > diferença entre os números for menor que o maior acréscimo
>> >> suportado
>> >> > pela plataforma:
>> >> >
>> >> > $ perl -E '
>> >> > if (0.2 > 0.19999999999999999999999999999999999999999999){
>> >> >> say "0.2 is greater than
>> >> 0.19999999999999999999999999999999999999";}
>> >> >> else {
>> >> >> say "Floating Point is not true real"};'
>> >> > Floating Point is not true real
>> >> > $
>> >> >
>> >> > $ perl -E '
>> >> > if (0.2 > 0.199999){
>> >> > say "0.2 is greater than 0.199999";}
>> >> > else {
>> >> > say "Floating Point is not true real"};'
>> >> > 0.2 is greater than 0.199999
>> >> > $
>> >> >
>> >> > Então, comparar pontos flutuantes não é seguro. Nem igualdade, 
>> nem
>> >> > maio, nem menor.
>> >> >
>> >> > E mais: garanto que se você quer usar um número real como chave 
>> de
>> >> > Hash você tem um problema na análise da lógica do problema que
>> >> está
>> >> > enfrentando e como solucioná-lo.
>> >> >
>> >> >
>> >> > Em 2012-11-29 10:36, Blabos de Blebe escreveu:
>> >> >> Na verdade é o contrário, não?
>> >> >>
>> >> >> Não se compara reais por igualdade.
>> >> >>
>> >> >> Se você usa reais como chaves de hash, você tem algum 
>> problema...
>> >> >>
>> >> >> Ao não controlar a representação interna em ponto flutuante, 
>> você
>> >> >> pode
>> >> >> nunca mais alcançar o valor relacionado à chave, se usar um
>> >> número
>> >> >> real como chave, pois qualquer bit diferente, mesmo que
>> >> arredondando
>> >> >> no mesmo número vai resultar num cálculo diferente na tabela
>> >> hash.
>> >> >>
>> >> >> Igualdade entre númros reais constuma ser definida como algo
>> >> assim:
>> >> >>
>> >> >> sub float_equal {
>> >> >> my ($first, $second) = @_;
>> >> >> my $threshold = 0.00000001 # arbitrário
>> >> >> return abs( $first - $second ) < $threshold;
>> >> >> }
>> >> >>
>> >> >> Converter para string antes de usar como chave de hash também 
>> não
>> >> me
>> >> >> parece saudável, pois, embora a string vá funcionar bem no 
>> hash,
>> >> >> você
>> >> >> não garante que a conversão vai resultar sempre na mesma 
>> string,
>> >> e
>> >> >> aí
>> >> >> vc se ferra do mesmo jeito.
>> >> >>
>> >> >> Por outro lado, se você nunca vai acessar o elemento do hash
>> >> através
>> >> >> da chave, um foreach por keys() ou values() vai te retornar os
>> >> >> valores...
>> >> >>
>> >> >> Mas aí eu te perguntaria por que rails você está usando hash 
>> pra
>> >> >> isso...
>> >> >>
>> >> >>
>> >> >>
>> >> >> On Thu, Nov 29, 2012 at 6:47 AM, <thiagoglauco em ticursos.net>
>> >> wrote:
>> >> >>> Existe um problema aqui, diferente da comparação.
>> >> >>> A comparação de reais é problemática devido a estrutura 
>> interna
>> >> do
>> >> >>> ponto
>> >> >>> flutuante. NÃO SE COMPARA REAIS POR MAIOR OU MENOR.Isso não é 
>> do
>> >> >>> Perl, mas
>> >> >>> das regras de aproximação usada pelos processadores.
>> >> >>>
>> >> >>> Rounding rules
>> >> >>>
>> >> >>> The standard defines five rounding rules. The first two round 
>> to
>> >> a
>> >> >>> nearest
>> >> >>> value; the others are called directed roundings:
>> >> >>> Roundings to nearest
>> >> >>>
>> >> >>> Round to nearest, ties to even – rounds to the nearest value;
>> >> >>> if the
>> >> >>> number falls midway it is rounded to the nearest value with 
>> an
>> >> even
>> >> >>> (zero)
>> >> >>> least significant bit, which occurs 50% of the time; this is 
>> the
>> >> >>> default for
>> >> >>> binary floating-point and the recommended default for 
>> decimal.
>> >> >>> Round to nearest, ties away from zero – rounds to the nearest
>> >> >>> value; if
>> >> >>> the number falls midway it is rounded to the nearest value 
>> above
>> >> >>> (for
>> >> >>> positive numbers) or below (for negative numbers); this is
>> >> intended
>> >> >>> as an
>> >> >>> option for decimal floating point.
>> >> >>>
>> >> >>> Directed roundings
>> >> >>>
>> >> >>> Round toward 0 – directed rounding towards zero (also known 
>> as
>> >> >>> truncation).
>> >> >>> Round toward +∞ – directed rounding towards positive infinity
>> >> >>> (also
>> >> >>> known as rounding up or ceiling).
>> >> >>> Round toward −∞ – directed rounding towards negative infinity
>> >> >>> (also
>> >> >>> known as rounding down or floor).
>> >> >>>
>> >> >>> Se a comparação for inevitável, converta o seu número para
>> >> string e
>> >> >>> compare
>> >> >>> ou determine um nível de precisão aceitável e faça bit a bit.
>> >> >>>
>> >> >>> Em 2012-11-28 21:42, Aureliano Guedes escreveu:
>> >> >>>>
>> >> >>>> Ola Monges.
>> >> >>>>
>> >> >>>> Estou com um problema simples mas que não acho a solução.
>> >> >>>>
>> >> >>>> Eu tenho um hash onde as chaves são valores numericos reais 
>> (a
>> >> >>>> maioria negativo e quase nenhum inteiro).
>> >> >>>> Estou limitando esses valores por um maximo e um minimo.
>> >> >>>>
>> >> >>>> foreach my $keys (keys %d) {
>> >> >>>> if ($keys <= $min and $keys >= $max) {
>> >> >>>> print "$d{$keys}";
>> >> >>>> }
>> >> >>>> }
>> >> >>>>
>> >> >>>> Problema que não da certo.
>> >> >>>> Ha algo de errado aqui??
>> >> >>>>
>> >> >>>> _______________________________________________
>> >> >>>> Rio-pm mailing list
>> >> >>>> Rio-pm em pm.org
>> >> >>>> http://mail.pm.org/mailman/listinfo/rio-pm
>> >> >>>
>> >> >>>
>> >> >>> _______________________________________________
>> >> >>> Rio-pm mailing list
>> >> >>> Rio-pm em pm.org
>> >> >>> http://mail.pm.org/mailman/listinfo/rio-pm
>> >> >> _______________________________________________
>> >> >> Rio-pm mailing list
>> >> >> Rio-pm em pm.org
>> >> >> http://mail.pm.org/mailman/listinfo/rio-pm
>> >> >
>> >> > _______________________________________________
>> >> > Rio-pm mailing list
>> >> > Rio-pm em pm.org
>> >> > http://mail.pm.org/mailman/listinfo/rio-pm
>> >>
>> >> _______________________________________________
>> >> Rio-pm mailing list
>> >> Rio-pm em pm.org
>> >> http://mail.pm.org/mailman/listinfo/rio-pm
>> >
>> > _______________________________________________
>> > Rio-pm mailing list
>> > Rio-pm em pm.org
>> > http://mail.pm.org/mailman/listinfo/rio-pm
>>
>> _______________________________________________
>> Rio-pm mailing list
>> Rio-pm em pm.org
>> http://mail.pm.org/mailman/listinfo/rio-pm
>
> _______________________________________________
> Rio-pm mailing list
> Rio-pm em pm.org
> http://mail.pm.org/mailman/listinfo/rio-pm



Mais detalhes sobre a lista de discussão Rio-pm