[26122] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 8315 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Aug 11 18:05:25 2005

Date: Thu, 11 Aug 2005 15:05:07 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Thu, 11 Aug 2005     Volume: 10 Number: 8315

Today's topics:
        Perl numerics: EPSILON and equality between floats <please_post@nomail.edu>
    Re: Perl numerics: EPSILON and equality between floats xhoster@gmail.com
    Re: Perl numerics: EPSILON and equality between floats <please_post@nomail.edu>
    Re: Perl Solaris/Linux LASTLOG <RedGrittyBrick@SpamWeary.foo>
        Review of "Pro Perl Debugging" <foo@pcunix.com>
        sort <nobody@nowhere.no>
    Re: sort <steve@uptime.org.uk>
    Re: sort <nobull@mail.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Thu, 11 Aug 2005 18:05:36 +0000 (UTC)
From: bill <please_post@nomail.edu>
Subject: Perl numerics: EPSILON and equality between floats
Message-Id: <ddg41g$j7u$1@reader2.panix.com>





I just recently came across this snippet: 

  my $EPSILON = 1;
  $EPSILON /= 2 while 0.5 + $EPSILON/2 > 0.5;

where $EPSILON was later used, e.g., to compare floats for equality:

  sub float_equal {
    my ($x, $y) = @_;
    return !($x||$y) || ($x+$y) && abs(($x-$y)/($x+$y)) < $EPSILON;
  }

(The above is the gist of what I recall, not verbatim production
code, but I think I got it right.)

I'm not very knowledgeable about numerics, so I was wondering
whether this was the best way to compare floats for equality.

I thought that this would be a FAQ, but I couldn't find it.

The first edition of The Perl Cookbook recommends converting both
numbers to the same string format, and then doing a string comparison:

 sub equal {
   my ($A, $B, $dp) = @_;
   return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B);
 }

The main reason I don't like this approach is that, in my experience,
some numerical objects, such as Math::BigFloat and Math::Pari,
don't work well with sprintf.

Also, I recall that in C there are pre-defined constants (e.g.
DBL_EPSILON in limits.h) that can be used for this kind of tests.
Is there something similar in Perl?

Many thanks in advance!

bill

P.S. If someone in Perl publishing reads this: a book on Perl
numerics is sorely needed (fundamentals, algorithms, recipes, best
practices) is sorely needed.



------------------------------

Date: 11 Aug 2005 20:00:34 GMT
From: xhoster@gmail.com
Subject: Re: Perl numerics: EPSILON and equality between floats
Message-Id: <20050811160034.410$ru@newsreader.com>

bill <please_post@nomail.edu> wrote:
> I just recently came across this snippet:
>
>   my $EPSILON = 1;
>   $EPSILON /= 2 while 0.5 + $EPSILON/2 > 0.5;
>
> where $EPSILON was later used, e.g., to compare floats for equality:
>
>   sub float_equal {
>     my ($x, $y) = @_;
>     return !($x||$y) || ($x+$y) && abs(($x-$y)/($x+$y)) < $EPSILON;
>   }
>
> (The above is the gist of what I recall, not verbatim production
> code, but I think I got it right.)
>
> I'm not very knowledgeable about numerics, so I was wondering
> whether this was the best way to compare floats for equality.

The best way to compare floats for equality is highly dependent on
why you want to compare floats for equality.

There are no magic bullets.

Xho

-- 
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service                        $9.95/Month 30GB


------------------------------

Date: Thu, 11 Aug 2005 20:59:09 +0000 (UTC)
From: bill <please_post@nomail.edu>
Subject: Re: Perl numerics: EPSILON and equality between floats
Message-Id: <ddge6t$jkr$1@reader2.panix.com>

In <20050811160034.410$ru@newsreader.com> xhoster@gmail.com writes:

>bill <please_post@nomail.edu> wrote:
>> I just recently came across this snippet:
>>
>>   my $EPSILON = 1;
>>   $EPSILON /= 2 while 0.5 + $EPSILON/2 > 0.5;
>>
>> where $EPSILON was later used, e.g., to compare floats for equality:
>>
>>   sub float_equal {
>>     my ($x, $y) = @_;
>>     return !($x||$y) || ($x+$y) && abs(($x-$y)/($x+$y)) < $EPSILON;
>>   }
>>
>> (The above is the gist of what I recall, not verbatim production
>> code, but I think I got it right.)
>>
>> I'm not very knowledgeable about numerics, so I was wondering
>> whether this was the best way to compare floats for equality.

>The best way to compare floats for equality is highly dependent on
>why you want to compare floats for equality.

That's interesting.  I can't think of any examples in which method
X would be better than method Y for some purposes but worse for
others.  Can you give an example?

In recent times, I've needed to compare floats in unit tests
(expected vs. obtained).  I typically use an approach similar to
the one I described in my OP (i.e. declare two floats as "equal"
if the difference between them is below some tolerance), except
that I just pull the tolerance out of thin air (I usually go for
2**-20, instead of having a halfway defensible procedure for
determining it.

bill




------------------------------

Date: Thu, 11 Aug 2005 18:40:20 +0000 (UTC)
From: RedGrittyBrick <RedGrittyBrick@SpamWeary.foo>
Subject: Re: Perl Solaris/Linux LASTLOG
Message-Id: <ddg62k$hgc$1@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com>

drew wrote:
> i have to process a large amount of data and i cannot perform this on 
> the invidual servers for either security sake or the way we have been 
> setup.
> 
> 
> here is the script from the  PERL COOKBOOK  to show the closest approach
> 
> #!/usr/bin/perl
> # laston - find out when given user last logged on
> use User::pwent;
> use IO::Seekable qw(SEEK_SET);
> 
> open (LASTLOG, "/var/log/lastlog") or die "can't open /usr/adm/lastlog: 
> $!";
> 
> $typedef = 'L A12 A16';  # linux fmt; sunos is "L A8 A16"
> $sizeof  = length(pack($typedef, ()));
> 
> for $user (@ARGV) {
>     $U = ($user =~ /^\d+$/) ? getpwuid($user) : getpwnam($user);
>     unless ($U) { warn "no such uid $user\n"; next; }
>     seek(LASTLOG, $U->uid * $sizeof, SEEK_SET) or die "seek failed: $!";
>     read(LASTLOG, $buffer, $sizeof) == $sizeof or next;
>     ($time, $line, $host) = unpack($typedef, $buffer);
>     printf "%-8s UID %5d %s%s%s\n", $U->name, $U->uid,
>           $time ? ("at " . localtime($time)) : "never logged in",
>           $line && " on $line",
>           $host && " from $host";
> }
> 
> 
> 
> 
> 
> 
> i have geathered all the passwd files/lastlog file for each server
> 
> how do i get getpwuid / getpwnam to work on the the password file that i 
> gathered and then work on the lastlog of the associated server?
> 

I'd not use getpwuid and getpwnam. I'd read the passwd files, split the 
records and store the UID and Name in a hash keyed by Login-ID. Then I'd 
use '$name{$user}' in place of 'getpwnam($user)'

I'd either keep each passwd and lastlog pair in its own directory named 
by server, or, I'd maybe prefix the filenames with servername and
iterate over a predefined list of server names.

YMMV.


------------------------------

Date: Thu, 11 Aug 2005 14:56:56 -0400
From: Tony Lawrence <foo@pcunix.com>
Subject: Review of "Pro Perl Debugging"
Message-Id: <W8ednT-HtaflAmbfRVn-gw@comcast.com>

Review of "Pro Perl Debugging" at 
http://aplawrence.com/Books/pro-perl-debugging.html


-- 
Tony Lawrence
Unix/Linux/Mac OS X  resources: http://aplawrence.com
Get published: http://aplawrence.com/publish.html


------------------------------

Date: Thu, 11 Aug 2005 21:38:20 GMT
From: Pietro <nobody@nowhere.no>
Subject: sort
Message-Id: <pan.2005.08.11.21.39.22.773715@nowhere.no>

Hallo, I made a little script that sort the lines of a file:

#! /usr/bin/perl

sub numerically {$a <=> $b;}

@array = <>;

@array = sort numerically (@array);

print (@array);

Maybe the code is not so good, but why if I give thi input file:

1.3.5.6
1.1.2.4
111.222.444.555
1.2.5.6
11.22.44.55
1.2.3.4
11.23.66.77
11.22.33.44
111.222.333.444
11.22.44.55
111.223.333.444
11.22.33.44
1.2.3.4
11.22.22.22
11.22.55.66
1.2.4.5
111.222.555.666
1.1.2.3
1.3.4.5

The result is this:

1.1.2.4
1.1.2.3
1.2.5.6
1.2.3.4
1.2.3.4
1.2.4.5
1.3.5.6
1.3.4.5
11.22.44.55
11.22.33.44
11.22.44.55
11.22.33.44
11.22.22.22
11.22.55.66
11.23.66.77
111.222.444.555
111.222.333.444
111.222.555.666
111.223.333.444

As I see perl sots only the first two field delimited by a ".", the others
are inserted as a fifo, first line encountered first line wrote in output,
why doesn't perl compare all the line?

Thanks, Pietro.
-- 
I will build myself a copper tower
With four ways out and no way in
But mine the glory, mine the power
(So I chose AmigaOS and GNU/Linux)



------------------------------

Date: Thu, 11 Aug 2005 22:43:43 +0000
From: Stephen Hildrey <steve@uptime.org.uk>
Subject: Re: sort
Message-Id: <1123796615.2711.0@lotis.uk.clara.net>

Pietro wrote:
> As I see perl sots only the first two field delimited by a ".", the others
> are inserted as a fifo, first line encountered first line wrote in output,
> why doesn't perl compare all the line?

You're using a *numeric* sort. "1.3.5.6" etc are not numbers.

If you had "use warnings;", you would see a load of these:

Argument "1.1.2.4\n" isn't numeric in numeric comparison (<=>)

Steve


------------------------------

Date: Thu, 11 Aug 2005 22:51:06 +0100
From: Brian McCauley <nobull@mail.com>
Subject: Re: sort
Message-Id: <ddgh8c$qf$1@redhat2.bham.ac.uk>

Pietro wrote:

> sub numerically {$a <=> $b;}
> 
> Maybe the code is not so good, but why if I give thi input file:
> 
> 1.3.5.6
> 1.1.2.4
> 111.222.444.555

> As I see perl sots only the first two field delimited by a ".", the others
> are inserted as a fifo, first line encountered first line wrote in output,

No, Perl sort the strings as numbers. If you convert the string 
'1.3.5.6' to a number then you get the number 1.3 (and you'll get a 
warning too if you've enabled warnings.

Sounds to me like you may want to compare the strings as IP address.

There are modules on CPAN to manipulate IP addresses.



------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc.  For subscription or unsubscription requests, send
#the single line:
#
#	subscribe perl-users
#or:
#	unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.  

NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice. 

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V10 Issue 8315
***************************************


home help back first fref pref prev next nref lref last post