/ Forside / Teknologi / Udvikling / Perl / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Perl
#NavnPoint
bjarneA 141
poul_from 50
soccer 30
Nicknack 14
Tmpj 0
max i liste ?
Fra : Peter


Dato : 02-06-01 17:13

Hej

Jeg har en liste "@liste" der f.eks indeholder [10,200,30,20]

Jeg vil nu gerne have fat i det højeste tal (200) alá:

$max= max (@liste);

Hvodden gør jeg det lettest ?

--
Venlig hilsen

Peter Heinzl
Mail: peter@cgi-shop.dk
web: www.cgi-shop.dk



 
 
Lars Balker Rasmusse~ (02-06-2001)
Kommentar
Fra : Lars Balker Rasmusse~


Dato : 02-06-01 17:27

"Peter" <peter@cgi-shop.dk> writes:
> Jeg har en liste "@liste" der f.eks indeholder [10,200,30,20]
>
> Jeg vil nu gerne have fat i det højeste tal (200) alá:
>
> $max= max (@liste);
>
> Hvodden gør jeg det lettest ?

sub max(\@) {
my($listref) = @_;
( sort {$a <=> $b} @{$listref} )[ $#{$listref} ]
}
$max = max (@liste);
--
Lars Balker Rasmussen "Woo hoo!?"

Peter (02-06-2001)
Kommentar
Fra : Peter


Dato : 02-06-01 17:42

Mange tak !

--
Venlig hilsen

Peter Heinzl



Adam Sjøgren (02-06-2001)
Kommentar
Fra : Adam Sjøgren


Dato : 02-06-01 18:00

On 02 Jun 2001 18:26:35 +0200, Lars Balker Rasmussen wrote:

> sub max(\@) {
> my($listref) = @_;
> ( sort {$a <=> $b} @{$listref} )[ $#{$listref} ]
> }
> $max = max (@liste);

Er'ed ikke overkill at sortere listen for at finde den største? (i
princip, altså, næppe i praksis).

En uden sortering:

sub max_scan(\@) {
my($listref)=@_;

my $max=${$listref}[0];
map { $max=$_ if $max<$_ } @{$listref};
return $max;
}

Lidt længere - og lidt hurtigere:

Benchmark: timing 1000000 iterations of max, max_scan...
max: 9 wallclock secs ( 8.55 usr + 0.00 sys = 8.55 CPU) @ 116959.06/s (n=1000000)
max_scan: 8 wallclock secs ( 7.51 usr + 0.00 sys = 7.51 CPU) @ 133155.79/s (n=1000000)

(Testet med:

my @liste=(100..100000);

timethese(1000000, {
'max' => 'max(@liste)',
'max_scan' => 'max_scan(@liste)'
}
);

der skal store størrelser til før man kan måle forskel...)


Mvh.

--
"Bob Dylan? Han har en cool röst." Adam Sjøgren
asjo@koldfront.dk

Lars Balker Rasmusse~ (02-06-2001)
Kommentar
Fra : Lars Balker Rasmusse~


Dato : 02-06-01 18:15

asjo@koldfront.dk (Adam Sjøgren) writes:
> Er'ed ikke overkill at sortere listen for at finde den største? (i
> princip, altså,

Jo.

> næppe i praksis).

Nemlig.
--
Lars Balker Rasmussen "Woo hoo!?"

Lauritz Jensen (02-06-2001)
Kommentar
Fra : Lauritz Jensen


Dato : 02-06-01 18:20

Adam Sjøgren wrote:
>
> (Testet med:
>
> my @liste=(100..100000);

Bemærk at du måske giver "soteringsmethoden" en fordel ved at give den
"allerede sortet" data som input. Jeg kender ikke perls sortering, men
den kunne kortslutte ved sorteret data og dermed får sorteringen ned på
samme kørertid som skanningen, nemlig O(n). Normalt (aka. med rigtige,
levede data) vil en sortering ikke kunne komme under O(n * log n), hvis
jeg husker rigtigt.

--
Lauritz

Adam Sjøgren (02-06-2001)
Kommentar
Fra : Adam Sjøgren


Dato : 02-06-01 18:41

On 02 Jun 2001 18:59:36 +0200, Adam Sjøgren wrote:

> Lidt længere - og lidt hurtigere:

> Benchmark: timing 1000000 iterations of max, max_scan...

Ignorér venligst denne del af min foregående artikel - det var noget
vrøvl (jeg havde ikke læst nok af Benchmark modulets manual - det jeg
har gjort er ihvertfald galt


Mvh.

--
"Bob Dylan? Han har en cool röst." Adam Sjøgren
asjo@koldfront.dk

Adam Sjøgren (02-06-2001)
Kommentar
Fra : Adam Sjøgren


Dato : 02-06-01 20:33

On 02 Jun 2001 18:59:36 +0200, Adam Sjøgren wrote:

> Er'ed ikke overkill at sortere listen for at finde den største? (i
> princip, altså, næppe i praksis).

Faktisk overhovedet slet ikke i praksis, ser det ud til:

virgil$ bin/maxtest 100000 a 100; bin/maxtest 100000 d 100; bin/maxtest 100000 r 100;
Testing functions: 100000 100000 100000
Benchmark: timing 100 iterations of max, max_naive, max_scan...
max: 27 wallclock secs (26.59 usr + 0.00 sys = 26.59 CPU) @ 3.76/s (n=100)
max_naive: 212 wallclock secs (211.76 usr + 0.02 sys = 211.78 CPU) @ 0.47/s (n=100)
max_scan: 144 wallclock secs (143.96 usr + 0.02 sys = 143.98 CPU) @ 0.69/s (n=100)
s/iter max_naive max_scan max
max_naive 2.12 -- -32% -87%
max_scan 1.44 47% -- -82%
max 0.266 696% 441% --
Testing functions: 100000 100000 100000
Benchmark: timing 100 iterations of max, max_naive, max_scan...
max: 30 wallclock secs (30.20 usr + 0.00 sys = 30.20 CPU) @ 3.31/s (n=100)
max_naive: 201 wallclock secs (200.20 usr + 0.07 sys = 200.27 CPU) @ 0.50/s (n=100)
max_scan: 134 wallclock secs (134.01 usr + 0.00 sys = 134.01 CPU) @ 0.75/s (n=100)
s/iter max_naive max_scan max
max_naive 2.00 -- -33% -85%
max_scan 1.34 49% -- -77%
max 0.302 563% 344% --
Testing functions: 99999 99999 99999
Benchmark: timing 100 iterations of max, max_naive, max_scan...
max: 80 wallclock secs (80.40 usr + 0.00 sys = 80.40 CPU) @ 1.24/s (n=100)
max_naive: 338 wallclock secs (336.62 usr + 0.08 sys = 336.70 CPU) @ 0.30/s (n=100)
max_scan: 274 wallclock secs (267.12 usr + 0.24 sys = 267.36 CPU) @ 0.37/s (n=100)
s/iter max_naive max_scan max
max_naive 3.37 -- -21% -76%
max_scan 2.67 26% -- -70%
max 0.804 319% 233% --
virgil$

Jeg kan ikke komme med andre gæt end: 1) sort er optimeret godt og
grundigt og/eller 2) jeg har dummet mig i mit andet forsøg med
Benchmark modulet.

Her er det program jeg fik tampet sammen (jeg ku' ikke lige finde ud
af at undgå de dér fjollede test_* funktioner - gode råd er meget
velkomne!):

#!/usr/bin/perl

use strict;
use warnings;

use Benchmark qw(cmpthese timediff timestr);


##### Subs:

sub max(\@) {
my($listref) = @_;
( sort {$a <=> $b} @{$listref} )[ $#{$listref} ];
}

sub max_scan(\@) {
my($listref)=@_;

my $max=${$listref}[0];
map { $max=$_ if $max<$_ } @{$listref};
return $max;
}

sub max_naive
{
my(@list)=@_;

my $max=$list[0];
map { $max=$_ if $max<$_ } @list;
return $max;
}

##### Init:

my $l=shift @ARGV;
my $type=shift @ARGV;
my @liste=create_list($type);

##### Args:

sub test_max
{
max(@liste);
}

sub test_max_scan
{
max_scan(@liste);
}

sub test_max_naive
{
max_naive(@liste);
}

##### Utility:

sub create_list
{
my($type)=@_;

if( $type eq "a" )
{
return (0..$l);
}
elsif( $type eq "d" )
{
return reverse(0..$l);
}
elsif( $type eq "r" )
{
my @liste;
srand(42); # Ensure same random list every time
map { push @liste, int(rand($l)) } (0..$l);
return @liste;
}
else
{
die "Unknown type: $type";
}
}

##### Run:

print "Testing functions: ";
print max(@liste) . " " . max_naive(@liste) . " " . max_scan(@liste) . "\n";

cmpthese(shift @ARGV,
{
   'max' => 'test_max()',
   'max_naive' => 'test_max_naive()',
   'max_scan' => 'test_max_scan()',
});

exit 0;


--
"Bob Dylan? Han har en cool röst." Adam Sjøgren
asjo@koldfront.dk

Thorbjørn Ravn Ander~ (03-06-2001)
Kommentar
Fra : Thorbjørn Ravn Ander~


Dato : 03-06-01 19:38

Adam Sjøgren wrote:
>
> On 02 Jun 2001 18:59:36 +0200, Adam Sjøgren wrote:
>
> > Er'ed ikke overkill at sortere listen for at finde den største? (i
> > princip, altså, næppe i praksis).
>
> Faktisk overhovedet slet ikke i praksis, ser det ud til:

> Jeg kan ikke komme med andre gæt end: 1) sort er optimeret godt og
> grundigt og/eller 2) jeg har dummet mig i mit andet forsøg med
> Benchmark modulet.

sort kalder svjv den indbyggede qsort i libc. Den er hurtig, og Perl er
som altid langsom.

Du glemmer at tage højde for de forskellige konstanten i O(n) versus O(n
log n), og forskellen er åbenbart stor nok til at gøre udslaget.

Der hvor det bliver interessant er når n fordobler nogen gange. Hvordan
skalerer de to løsninger så? (eftersom det kun er en log n til forskel
kan vi godt komme til at snakke meget store værdier for n inden den
blive roverhalet.)

--
Thorbjørn Ravn Andersen "...plus...Tubular Bells!"
http://bigfoot.com/~thunderbear

Adam Sjøgren (04-06-2001)
Kommentar
Fra : Adam Sjøgren


Dato : 04-06-01 13:49

On Sun, 03 Jun 2001 19:37:42 +0100, Thorbjørn Ravn Andersen wrote:

>> Jeg kan ikke komme med andre gæt end: 1) sort er optimeret godt og
>> grundigt og/eller 2) jeg har dummet mig i mit andet forsøg med
>> Benchmark modulet.

> sort kalder svjv den indbyggede qsort i libc. Den er hurtig, og
> Perl er som altid langsom.

> Du glemmer at tage højde for de forskellige konstanten i O(n) versus
> O(n log n), og forskellen er åbenbart stor nok til at gøre udslaget.

Hvilken del af "sort er optimeret godt og grundigt" får du til at jeg
glemmer det?

(Grunden til at jeg medtog mulighed 2) er at jeg dummede mig på det
ekstremeste i mit første forsøg med Benchmark).

> Der hvor det bliver interessant er når n fordobler nogen gange.
> Hvordan skalerer de to løsninger så? (eftersom det kun er en log n
> til forskel kan vi godt komme til at snakke meget store værdier for
> n inden den blive roverhalet.)

Jeg har kun 128MB ram, så længe man holder sig inden for det er det
langt hurtigst at bruge max med sortering.

(Sjovt nok bliver den mere og mere overlegen jo større listerne er;
sammenlignet med max_scan med 10000 tilfældige elementer: 23%, ved
100000 elementer: 227%, ved 500000 elementer: 1294% - stadig med
forbehold for at jeg har dummet mig igen i det tidligere postede
program).

Der hvor det er interessant er på de størrelser lister som man bruger
funktionen på i praksis


Mvh.

--
"Vi er s'guda lige glade med om det er jul eller onsdag!" Adam Sjøgren
asjo@koldfront.dk

Thorbjørn Ravn Ander~ (04-06-2001)
Kommentar
Fra : Thorbjørn Ravn Ander~


Dato : 04-06-01 23:49

Adam Sjøgren wrote:

> Hvilken del af "sort er optimeret godt og grundigt" får du til at jeg
> glemmer det?

Godt spørgsmål. Til gengæld kan jeg heller ikke se at du husker det...

> (Sjovt nok bliver den mere og mere overlegen jo større listerne er;
> sammenlignet med max_scan med 10000 tilfældige elementer: 23%, ved
> 100000 elementer: 227%, ved 500000 elementer: 1294% - stadig med
> forbehold for at jeg har dummet mig igen i det tidligere postede
> program).

Det antyder jo kraftigt at det ikke er O( 1) at slå op i et array.


--
Thorbjørn Ravn Andersen "...plus...Tubular Bells!"
http://bigfoot.com/~ravn


Trond Michelsen (02-06-2001)
Kommentar
Fra : Trond Michelsen


Dato : 02-06-01 18:18

Lars Balker Rasmussen <lars@balker.org> skrev i
meldingsnyheter:ur8x2df0k.fsf@balker.org...
>> Jeg har en liste "@liste" der f.eks indeholder [10,200,30,20]
>> Jeg vil nu gerne have fat i det højeste tal (200) alá:
>> $max= max (@liste);
>> Hvodden gør jeg det lettest ?
> sub max(\@) {
> my($listref) = @_;
> ( sort {$a <=> $b} @{$listref} )[ $#{$listref} ]
> }
> $max = max (@liste);

Når man bare vil ha det høyeste (eller laveste) tallet fra en liste, er det
unødvendig å sortere hele listen. Men sålenge listen ikke er veldig stor, så
har det nok ikke så mye å si.

sub max (\@) {
my ($listref) = @_;
my $max = $listref->[0];
foreach my $i (0..@$listref) {
$max = $listref->[$i] if $listref->[$i] > $max;
}
return $max;
}

$max = max @liste;

--
Trond Michelsen




Thorbjørn Ravn Ander~ (03-06-2001)
Kommentar
Fra : Thorbjørn Ravn Ander~


Dato : 03-06-01 19:34

Peter wrote:

> Jeg vil nu gerne have fat i det højeste tal (200) alá:
>
> $max= max (@liste);
>
> Hvodden gør jeg det lettest ?

Hvad med så'rn?

   perl -e "$max = (sort (2,4,6,8,1,3,5))[-1]; print $max"

--
Thorbjørn Ravn Andersen "...plus...Tubular Bells!"
http://bigfoot.com/~thunderbear

Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408914
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste