2010-07-09 24 views
7

mam ten kawałek skryptu:Dziwne zachowanie rodzaju

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 

my @arr = (
    { 
     name => 'foo', 
     value => 123, 
    }, 
    { 
     name => 'bar', 
     value => 'nan', 
    }, 
    { 
     name => 'foobar', 
     value => 456, 
    }, 
); 

@arr = sort {$a->{value} <=> $b->{value} } @arr; 

print Dumper(\@arr); 

nie mam żadnych problemów w systemie Windows XP/Strawberry Perl 5.10.1

albo Linux 2.6.12-1 i386/Perl v5.8.5 zbudowane dla i386-linux-thread-multi,

ale pod Linuksem 2.6.18-53/Perl v5.8.8 zbudowany dla x86_64-linux-thread-multi, mam komunikat o błędzie:

Sort subroutine didn't return a numeric value at testsort.pl line 21. 

Co jest nie tak i jak mogę to naprawić?

+0

Czy to samo się stanie, jeśli uprościsz to w ten sposób? @arr = sort {$ a <=> $ b} (123, 'nan', 456); – wdebeaum

+0

@wdebeaum: brak błędów w jednej linijce, ale nie sortuje niczego pod x86_64, podczas gdy wszystko jest OK pod XP wygrywa i i386 – Toto

Odpowiedz

6

W niektórych kompilacjach "nan" jest wymuszane na wartość 0 dla porównania <=>, a sortowanie powiedzie się. W innych kompilacjach nan jest traktowane jako "nie liczba", a wartość zwracana z <=> jest niezdefiniowana.

Dla maksymalnej przenośności, sprawdzić wartość dla tego, czy jest to dobra liczba nie:

(isnan podprogram od How do I create or test for NaN or infinity in Perl?):

sub isnan { ! defined($_[0] <=> 9**9**9) } 

@arr = sort { isnan($a->{value}) ? 0 : $a->{value} 
         <=> 
       isnan($b->{value}) ? 0 : $b->{value} } @arr; 
+0

To działa. Otworzyłem trójskładnik przez nawias. – Toto

4

2 Solutions

  1. mobrule Rozwiązanie:

    sub isnan { ! defined($_[0] <=> 9**9**9) } 
    @arr = sort { isnan($a->{value}) ? 0 : $a->{value} 
               <=> 
           isnan($b->{value}) ? 0 : $b->{value} } @arr; 
    
  2. Perldoc „s rozwiązanie:

    @result = sort { $a <=> $b } grep { $_ == $_ } @input; 
    

  1. Daje swoją NaN wartość 0, który należy przesunąć ją w górę listy.
  2. Uzyskuje przewagę, że NaN != NaN, aby wyeliminować wszystkie NaN s z listy wejściowej.

Jak mobrule wspomniano, jest to spowodowane przez porównanie NaN między buduje.