Rounding up in perl

T

Tim Greer

Ilya said:
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Tim Greer
Nevertheless, someone I actually used to respect for their
contributions has resorted to acting like this and aligning their
logic with a poster
that doesn't know what the /x modifer if for. Food for thought (not
that I expect it to matter).

Yes, do REALLY think about it, please.

I would GLADLY "align" my logic with sln/xee/godzilla/whoever as far
as what they say in a particular moment makes sense. Likewise in the
opposite direction.

Hope this helps,
Ilya

I don't fault you at all, if you agree with them, I'd do the same.
Perhaps I wasn't clear, or perhaps I'm just on the other side of the
fence on this one. No matter though. Thanks.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was NOT [per weedlist] sent to
Tim Greer
And that is what I said previously, it's not probably want you want,
since it's intent is to truncate (even if that is a method used for
rounding),

When posting on Usenet, one should keep in mind that there is a
certain proportion of readers who are ESP-challenged. Maybe what you
said was what you claim; but what is important is what you WROTE.
and I think that it's not as dependable as other solutions,

Could you please expand on this word "dependable" you use so much in
this thread? I puzzle over which particular meaning you associate
with this word in the context of int()?

Thanks,
Ilya
 
T

Tim Greer

Ilya said:
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Tim Greer
And that is what I said previously, it's not probably want you want,
since it's intent is to truncate (even if that is a method used for
rounding),

When posting on Usenet, one should keep in mind that there is a
certain proportion of readers who are ESP-challenged. Maybe what you
said was what you claim; but what is important is what you WROTE.

Reading what someone wrote is also important. Perhaps my wording was
poor in some responses, but I did make it clear that while you can use
it for rounding, it's probably not the best method, since it's actually
truncation. If it works within the confines of your approach or goal,
then no harm and no foul.
Could you please expand on this word "dependable" you use so much in
this thread?

I suppose that was a poorly used term in the capacity in which I
intended it to convey. In other words, I wouldn't call sln's solution
"dependable" (I mentioned the poor use regarding his example, and I
guess that was confusing, as a couple of people thought that meant I
said that int() couldn't be used as a method of rounding -- it can,
it's just probably not a good idea -- unless it does work "well enough"
for what your intended goal is).

I said that while int() can be used to round, that is not its intended
design (it is to truncate). In reply, you seemed to insist that int()
was indeed "intended" to round, but maybe I misread that? Anyway,
we're not getting anywhere new with this, so please disregard it. If I
misunderstood, I apologize.
 
S

sln

Ilya said:
[A complimentary Cc of this posting was sent to

There's no need for the complimentary Cc. I read it here, I don't need
to read it in email as well. Thanks.
Tim Greer




Write correct documentation...

You're welcome to write the correct documentation yourself, since you
disagree with it.
Exactly as well as any other rounding methed.

Except it doesn't round up as a value to an integer as well as sprintf,
and the fact that truncation isn't "exactly" rounding.
int() gives a precise answer. By definition, a precise (and correct
;-) answer can't be "non-accurate".

See the documentation. If you disagree with it, submit something that's
correct. Argue semantics all you like, it truncates, it doesn't round.
I suppose if you think that's the same effect, I can't help.
Documentation is absolutely wrong.

Why not submit something that's correct?
Nevertheless.

Nevertheless, someone I actually used to respect for their contributions
has resorted to acting like this and aligning their logic with a poster
that doesn't know what the /x modifer if for. Food for thought (not
that I expect it to matter).

Btw, I know what /x is for. If I wan't to tell you how my long ass
regular expression is used I will. If not I won't. Simple as that.
Otherwise, figure it out for yourself.

sln
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was NOT [per weedlist] sent to
Tim Greer
Reading what someone wrote is also important.

Very true; unfortunately, on Usenet one must expect that only
negligible percentage of readers would do it. (Especially of you
expect them to disregard what is written explicitly, and somehow read
the meaning between the lines. ;-)
Perhaps my wording was poor in some responses,

This is why many people jumped in to fix it. Your postings remain
available for googling; if they remain unfixed, they would forever add
"insult by confirming" the permanent injury which is the current Perl docs...
I suppose that was a poorly used term in the capacity in which I
intended it to convey. In other words, I wouldn't call sln's solution
"dependable" (I mentioned the poor use regarding his example, and I
guess that was confusing, as a couple of people thought that meant I
said that int() couldn't be used as a method of rounding -- it can,
it's just probably not a good idea -- unless it does work "well enough"
for what your intended goal is).

Hmm, it looks like you support the school of "programming by voodoo".
"Try several random chunks of code, and leave the one which gives
results most similar to the target of the exercise." :-(

From my point of view, there are only two types of solutions: correct
ones, and incorrect ones. [Of course, all the Perl stuff in the first
category may still be made unusable by bugs in perl; the additional
complication is that as practice shows, the first category is empty.
;-) :-(]
In reply, you seemed to insist that int() was indeed "intended" to
round, but maybe I misread that?

It looks like you advocate "reading", but are still guilty of the
opposite. Have not it been beaten to death yet that

the intent of int() is to round to zero (often called "truncation");

rounding to zero is one of the forms of rounding?

Probably a linguistic problem: you may just think that "rounding" is a
much less rich notion than it is in reality. There are MANY different
context where rounding is called for, and each context requires its
own semantic; but 5 different semantics (with 2..3 subflavors) are the
most often used...

Yours,
Ilya
 
T

Tim Greer

Btw, I know what /x is for. If I wan't to tell you how my long ass
regular expression is used I will. If not I won't. Simple as that.
Otherwise, figure it out for yourself.

I know exactly what it's doing. The fact you should use the /x modifier
is an indication of your lack of understanding your own regex, not
mine.
 
T

Tim Greer

Ilya said:
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Tim Greer
Reading what someone wrote is also important.

Very true; unfortunately, on Usenet one must expect that only
negligible percentage of readers would do it. (Especially of you
expect them to disregard what is written explicitly, and somehow read
the meaning between the lines. ;-)

If you mean "between the lines" as in when I followed up and
specifically clarified not being taken into account, because it
wouldn't justify continuing marking snide remarks, yes.
This is why many people jumped in to fix it.

I think just you (and sln).
Your postings remain
available for googling;
Yes.

if they remain unfixed, they would forever add
"insult by confirming" the permanent injury which is the current Perl
docs...

Not really.

Hmm, it looks like you support the school of "programming by voodoo".
"Try several random chunks of code, and leave the one which gives
results most similar to the target of the exercise." :-(

Not really.
From my point of view, there are only two types of solutions: correct
ones, and incorrect ones. [Of course, all the Perl stuff in the first
category may still be made unusable by bugs in perl; the additional
complication is that as practice shows, the first category is empty.
;-) :-(]
In reply, you seemed to insist that int() was indeed "intended" to
round, but maybe I misread that?

It looks like you advocate "reading", but are still guilty of the
opposite. Have not it been beaten to death yet that

the intent of int() is to round to zero (often called "truncation");

rounding to zero is one of the forms of rounding?

Probably a linguistic problem: you may just think that "rounding" is a
much less rich notion than it is in reality. There are MANY different
context where rounding is called for, and each context requires its
own semantic; but 5 different semantics (with 2..3 subflavors) are the
most often used...

Saying one thing is intended for another thing than it actually is,
because you can use it for that other thing, isn't correct logic in my
view. I honestly don't care, it was when sln insisted it is intended
*for* rounding. It is to truncate, it can be used to round, it is a
method of doing so. I've been very clear, so you know by now what I
meant, even if you misunderstood. That should really be the end of it,
unless you enjoy arguing. I don't, and you mentioned yourself that it
could be brought back up again. I have no desire to. I'm not even
seeing where the disagreement was if we both agree it can be used to
round. Who cares what the technical terms we disagree about its
intended purpose is, or how we word it or use it to mean one thing or
the other. I don't. Surely you don't either, so let's end it (either
way, I'm done, since there's nothing more to say)...
 
P

Peter J. Holzer

Right. I am well aware of that, and I even said so as well before Ilya
replied.


And that is what I said previously, it's not probably want you want,
since it's intent is to truncate (even if that is a method used for
rounding),

We may have a language problem here. I wouldn't say "truncating is a
method used for rounding", but "truncating is a method of rounding". The
former implies that there is only one way of rounding, and truncating is
not rounding, but can be used to implement rounding. The latter implies
that there are many ways of rounding, and trucating is one of them.
and I think that it's not as dependable as other solutions,

Again, we may have a language problem. If I say a method is "not
dependable" I mean that it does give the expected result most of the
time, but sometimes it gives the wrong result, and the problem isn't
immediately apparent.

To borrow an example from a recent thread, replacing a symlink with

unlink($link) if -e $link;
symlink($target, $link);

is not dependable. It works almost all of the time, but there is a
possibility that another process creates $link between the time your
process has removed it and tries to recreate it - and unless you are
used to thinking about race conditions, you may not see that.

OTOH, if you do something like

$y = int($x) # round to nearest int

that's not a question of dependability. That will produce the wrong
answer for 50% of all possible values, and it is immediately apparent
from the definition of the int function, that it is the wrong function
to use in this case. (floor and ceil are of course, just as wrong).

Let's assume you want a function which rounds the way you learned in
primary school: Round to nearest integer, and break ties away from zero.

sub common_round_i { my ($x) = @_; return int($x); }

sub common_round_f { my ($x) = @_; return floor($x); }

sub common_round_c { my ($x) = @_; return ceil($x); }

sub common_round_s { my ($x) = @_; return sprintf("%.0f", $x); }

It is immediately clear that the first three implementations don't do
what you want. The first two round 0.9 down (instead of up) and
common_round_c rounds 0.1 up (instead of down).

common_round_s seems to do the right thing at the first glance:
It rounds 0.1 down, it rounds 0.9 up, it rounds 1.5 up. But it rounds
0.5 down (instead of up), and that is probably not immediately apparent
to someone who hasn't learned a bit about numerical methods. So you
could say that using sprintf is "not dependable" (for the problem you
want to solve - there are good reasons for sprintf working the way it
does and at that point you should probably consider the possibility that
"rounding the way you learned in primary school" may not be what you
really need), while the other ways are not only "not dependable", they
are clearly und utterly wrong.

However, you can use the int, floor, and ceil functions to implement
your rounding function:

sub common_round_i2 {
my ($x) = @_;
return int($x + ($x >= 0 ? 0.5 : -0.5));
}

sub common_round_f2 {
my ($x) = @_;
return $x >= 0 ? floor($x + 0.5) : -floor(-$x + 0.5);
}

sub common_round_c2 {
my ($x) = @_;
return $x >= 0 ? -ceil(-$x - 0.5) : ceil($x - 0.5);
}


All of these are correct (as per specification), and there is no
mathematical reason to prefer one over the others. But common_round_i2
is slightly shorter and doen't need any modules, so I'd prefer that from
a Perl programmer's view.

which I also listed -- which the docs themselves also warn against.

The warning in the documentation is highly confusing. Not really wrong,
but very misleading if you don't already know about these things (and
then you don't need the warning).

hp
 
P

Peter J. Holzer

Nevertheless, someone I actually used to respect for their contributions
has resorted to acting like this and aligning their logic with a poster
that doesn't know what the /x modifer if for.

As they say, even a blind man hits the mark sometimes. Just because sln
writes something it isn't automatically wrong.

hp
 
T

Tad J McClellan

Peter J. Holzer said:
As they say, even a blind man hits the mark sometimes. Just because sln
writes something it isn't automatically wrong.


Who would be so foolish as to fall into such a prejudice?


.... me, raises hand ...
 
S

sln

Here is a Perl ceil/floor equivalent. The first code section
seems to correctly implement floor by taking into account that
int() does not use the sign in its process of rounding. The
second code section with floor, although intuitive is not correct.
For a full proof, all the values between 2.0 - 2.9 should be checked.

sln

This is amended code and a full proof using standard C ceil/floor
as a comparison. This output is the perl code equavelent.

The previous versions is erroneous and can't use +- .5 as int()
rounds to the nearest whole number.

As it is now +- 1.0 is used as well as taking boundry conditions
into consideration.

The _ceil()/_floor() are eqavelent now. An effort was made towards
speedy code if thats possible.

Thanks Peter J. Holzer for pointing out the error.

The good thing about this code is it works the same way every time.
Now, back to the show...

sln

==================================================

# ===========================================
# A Perl based Ceil/floor equavelent
# This floor takes the sign into acount
# when rounding.
# - - - - - - - -
use strict;
use warnings;

## test ceil-floor around 0 and between (+-) 2.0 - 3.0
## in .1 increments

my @Test = qw(
0.0 0.1 0.6
2.0 2.1 2.3 2.4 2.5
2.6 2.7 2.8 2.9 3.0
);

my ($y,$z);

for $y (@Test)
{
$z = _ceil( $y );
printf( "The ceil of %s is %f\n", $y, $z );
$z = _ceil( -$y );
printf( "The ceil of -%s is %f\n\n", $y, $z );
}
for $y (@Test)
{
$z = _floor( $y );
printf( "The floor of %s is %f\n", $y, $z );
$z = _floor( -$y );
printf( "The floor of -%s is %f\n\n", $y, $z );
}

sub _ceil {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0]<0);
return int($_[0]+1.0);
}
sub _floor {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0]>=0);
return int($_[0]-1.0);
}


__END__


The ceil of 0.0 is 0.000000
The ceil of -0.0 is 0.000000

The ceil of 0.1 is 1.000000
The ceil of -0.1 is 0.000000

The ceil of 0.6 is 1.000000
The ceil of -0.6 is 0.000000

The ceil of 2.0 is 2.000000
The ceil of -2.0 is -2.000000

The ceil of 2.1 is 3.000000
The ceil of -2.1 is -2.000000

The ceil of 2.3 is 3.000000
The ceil of -2.3 is -2.000000

The ceil of 2.4 is 3.000000
The ceil of -2.4 is -2.000000

The ceil of 2.5 is 3.000000
The ceil of -2.5 is -2.000000

The ceil of 2.6 is 3.000000
The ceil of -2.6 is -2.000000

The ceil of 2.7 is 3.000000
The ceil of -2.7 is -2.000000

The ceil of 2.8 is 3.000000
The ceil of -2.8 is -2.000000

The ceil of 2.9 is 3.000000
The ceil of -2.9 is -2.000000

The ceil of 3.0 is 3.000000
The ceil of -3.0 is -3.000000

The floor of 0.0 is 0.000000
The floor of -0.0 is 0.000000

The floor of 0.1 is 0.000000
The floor of -0.1 is -1.000000

The floor of 0.6 is 0.000000
The floor of -0.6 is -1.000000

The floor of 2.0 is 2.000000
The floor of -2.0 is -2.000000

The floor of 2.1 is 2.000000
The floor of -2.1 is -3.000000

The floor of 2.3 is 2.000000
The floor of -2.3 is -3.000000

The floor of 2.4 is 2.000000
The floor of -2.4 is -3.000000

The floor of 2.5 is 2.000000
The floor of -2.5 is -3.000000

The floor of 2.6 is 2.000000
The floor of -2.6 is -3.000000

The floor of 2.7 is 2.000000
The floor of -2.7 is -3.000000

The floor of 2.8 is 2.000000
The floor of -2.8 is -3.000000

The floor of 2.9 is 2.000000
The floor of -2.9 is -3.000000

The floor of 3.0 is 3.000000
The floor of -3.0 is -3.000000
 
S

sln

[snip]
This is amended code and a full proof using standard C ceil/floor
as a comparison. This output is the perl code equavelent.

The previous versions is erroneous and can't use +- .5 as int()
rounds to the nearest whole number.

As it is now +- 1.0 is used as well as taking boundry conditions
into consideration.

The _ceil()/_floor() are eqavelent now. An effort was made towards
speedy code if thats possible.
[snip]

sub _ceil {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0]<0);
return int($_[0]+1.0); not needed ^^^
}
sub _floor {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0]>=0);
return int($_[0]-1.0); not needed ^^^
}
There is no need for a double call to int().
The last int() is not necessary. So it's speedier,
if there is such a thing.

sln

## -----------------------
## ceil/floor equavelent
## -----------------------

use strict;
use warnings;

## test ceil-floor around 0 and between (+-) 2.0 - 3.0

my @Test = qw(
0.0 0.1 0.6
2.0 2.1 2.3 2.4 2.5
2.6 2.7 2.8 2.9 3.0
);

my $y;

for $y (@Test)
{
printf( "The ceil of %s is %f\n", $y, _ceil( $y ) );
printf( "The ceil of -%s is %f\n\n", $y, _ceil( -$y ) );
}
for $y (@Test)
{
printf( "The floor of %s is %f\n", $y, _floor( $y ) );
printf( "The floor of -%s is %f\n\n", $y, _floor( -$y ) );
}

sub _ceil {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0] < 0.0);
return $z+1.0;
}
sub _floor {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0] >= 0.0);
return $z-1.0;
}

__END__
 
S

sln

Is there more than one function for rounding a
number up in perl?
I tried the ceil() function but get an undefined subroutine
message.
[snip]
This is amended code and a full proof using standard C ceil/floor
as a comparison. This output is the perl code equavelent.

The previous versions is erroneous and can't use +- .5 as int()
rounds to the nearest whole number.

As it is now +- 1.0 is used as well as taking boundry conditions
into consideration.

The _ceil()/_floor() are eqavelent now. An effort was made towards
^^^^^^^^^
equivalent
Not sure about the spelling. I'm dislexic so it looks right to me.

sln
 
S

sln

Is there more than one function for rounding a
number up in perl?
I tried the ceil() function but get an undefined subroutine
message.
[snip]
This is amended code and a full proof using standard C ceil/floor
as a comparison. This output is the perl code equavelent.

The previous versions is erroneous and can't use +- .5 as int()
rounds to the nearest whole number.

As it is now +- 1.0 is used as well as taking boundry conditions
into consideration.

The _ceil()/_floor() are eqavelent now. An effort was made towards
speedy code if thats possible.
[snip]

sub _ceil {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0]<0);
return int($_[0]+1.0); not needed ^^^
}
sub _floor {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0]>=0);
return int($_[0]-1.0); not needed ^^^
}
There is no need for a double call to int().
The last int() is not necessary. So it's speedier,
if there is such a thing.
[snip]

sub _ceil {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0] < 0.0);
return $z+1.0;
}
sub _floor {
my $z = int($_[0]);
return $z if ($_[0] == $z || $_[0] >= 0.0);
return $z-1.0;
}
Even better. Random statistics suggests ceil/floor will
not be called on boundries more than otherwise.

Therefore, the speediest solution possible is to check for
otherwise first. This will eliminate unecesarry boundry checks
in conditions that statistically predict other wise.

Speedier still, if there is such a thing.

sub _ceil {
my $z = int($_[0]);
return $z if ($_[0] < 0.0 || $_[0] == $z);
return $z+1.0;
}
sub _floor {
my $z = int($_[0]);
return $z if ($_[0] >= 0.0 || $_[0] == $z);
return $z-1.0;
}

Typically, this is the least common denominator conditional
logic that would be used in the C library if its not of
a mathematical nature in its assembly derivation.

sln
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top