Home > Archive > PERL Miscellaneous > February 2005 > Division/math bug in perl?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Division/math bug in perl?
|
|
|
| Why is this:
$ perl -e 'print (int (-2.6), "\n")'
-2
Shouldn't it be -3? I thought converting from float to int is supposed
to give the integer part, which is -3, and not round towards zero, as it
seems to be doing, resulting in -2? For that matter, why does c/c++ do
this too?
Any hand calculator I've tried gives -3 for int (-2.6), like a texas
instruments graphing calc.
To it's credit, perl correctly does mod func correctly:
$ perl -e 'print (-13 % 5, "\n")'
2
Where as in c/c++ you get -3, which is mathematically incorrect. (Any
hand calculator I've tried gives 2 for the above operation.)
| |
| darkon 2005-02-24, 8:57 pm |
| Snail <snail@localhost.com> wrote:
> Why is this:
>
> $ perl -e 'print (int (-2.6), "\n")'
> -2
>
> Shouldn't it be -3? I thought converting from float to int is
int() isn't really converting, it's just returning the integer part
of the number. See the docs.
> supposed to give the integer part, which is -3, and not round
But the integer part of -2.6 is -2, not -3.
> towards zero, as it seems to be doing, resulting in -2? For that
> matter, why does c/c++ do this too?
I don't know about c/c++, but this behaviour is explicitly documented
for Perl's int():
<quote>
int EXPR
int
Returns the integer portion of EXPR. If EXPR is omitted, uses
$_. You should not use this function for rounding: one because
it truncates towards 0, and two because machine representations
of floating point numbers can sometimes produce counterintuitive
results.
</quote>
| |
| A. Sinan Unur 2005-02-24, 8:57 pm |
| "Snail" <snail@localhost.com> wrote in news:cvleei$on4$1@news.astound.net:
> Subject: Division/math bug in perl?
Might arrogant coming from someone who is unable to read and understand
the documentation:
> Why is this:
>
> $ perl -e 'print (int (-2.6), "\n")'
> -2
C:\> perldoc -f int
int EXPR
int Returns the integer portion of EXPR. If EXPR is omitted, uses
$_. You should not use this function for rounding: one because
it truncates towards 0, and two because machine
representations of floating point numbers can sometimes
produce counterintuitive results. For example,
"int(-6.725/0.025)" produces -268 ...
Sinan
| |
| Chris Mattern 2005-02-24, 8:57 pm |
| Snail wrote:
> Why is this:
>
> $ perl -e 'print (int (-2.6), "\n")'
> -2
>
> Shouldn't it be -3? I thought converting from float to int is supposed
> to give the integer part, which is -3,
Er, huh? >>-2<<.6. The integer part of that sure looks like -2 to me.
^^
> and not round towards zero, as it
> seems to be doing, resulting in -2? For that matter, why does c/c++ do
> this too?
>
> Any hand calculator I've tried gives -3 for int (-2.6), like a texas
> instruments graphing calc.
>
> To it's credit, perl correctly does mod func correctly:
>
> $ perl -e 'print (-13 % 5, "\n")'
> 2
>
> Where as in c/c++ you get -3, which is mathematically incorrect. (Any
> hand calculator I've tried gives 2 for the above operation.)
--
Christopher Mattern
"Which one you figure tracked us?"
"The ugly one, sir."
"...Could you be more specific?"
| |
| Jeff Stampes 2005-02-24, 8:57 pm |
| Snail wrote:
> Why is this:
>
> $ perl -e 'print (int (-2.6), "\n")'
> -2
Because the docs say this:
stampes@flux[15] stampes > perldoc -f int
int EXPR
int Returns the integer portion of EXPR. If EXPR is omitted, uses
$_. You should not use this function for rounding: one because
it truncates towards 0, and two because machine representations
of floating point numbers can sometimes produce counterintu-
itive results. For example, "int(-6.725/0.025)" produces -268
rather than the correct -269; that's because it's really more
like -268.99999999999994315658 instead. Usually, the
"sprintf", "printf", or the "POSIX::floor" and "POSIX::ceil"
functions will serve you better than will int().
| |
| Anno Siegel 2005-02-24, 8:57 pm |
| Snail <snail@localhost.com> wrote in comp.lang.perl.misc:
> To it's credit, perl correctly does mod func correctly:
>
> $ perl -e 'print (-13 % 5, "\n")'
> 2
>
> Where as in c/c++ you get -3, which is mathematically incorrect. (Any
There is no universal definition of the modulo operation for negative
(or zero) operands. Mathematicians (and implementors) are free to define
it in any way they please.
> hand calculator I've tried gives 2 for the above operation.)
Oh.
Anno
| |
| Ala Qumsieh 2005-02-24, 8:57 pm |
| A. Sinan Unur wrote:
> "Snail" <snail@localhost.com> wrote in news:cvleei$on4$1@news.astound.net:
>
>
>
>
> Might arrogant coming from someone who is unable to read and understand
> the documentation:
I have read earlier posts from others pointing out that your comments
can be a bit harsh sometimes, and I agree with them. Your reply here
seems to me too condescending and uncalled for.
Personally, I value your contribution to clpmisc, but I urge you to
exercise more care before posting.
Just my two cents,
--Ala
| |
| A. Sinan Unur 2005-02-24, 8:57 pm |
| Ala Qumsieh <notvalid@email.com> wrote in
news:X_rTd.9055$Pz7.3342@newssvr13.news.prodigy.com:
> A. Sinan Unur wrote:
>
>
> I have read earlier posts from others pointing out that your comments
> can be a bit harsh sometimes, and I agree with them. Your reply here
> seems to me too condescending and uncalled for.
I don't know on this one. I think the "I don't need to read what a
function really does, if it does not do what I expect" attitude is quite
irritating. Incidentally, this is not a rare attitude. See Jill
Krugmann's post today.
On the other hand, I do value your opinion of me, so I'll have to figure
something out.
Thanks.
Sinan.
| |
| Alfred Z. Newmane 2005-02-24, 8:57 pm |
| darkon wrote:
> Snail <snail@localhost.com> wrote:
>
>
> int() isn't really converting, it's just returning the integer part
> of the number. See the docs.
>
>
> But the integer part of -2.6 is -2, not -3.
Not mathematically it isn't. I should be -3. Think of it like this. The
int part of 2.6 is 2, which is the /lowest/ number before the next
integer on the number line. Applying this to -2.6, the /lowest/ number
before the next integer is -3.
Maybe I can explain this better with an illustration:
Float: 1 .5 2 .5 3
2.6
| - - - - + - - - - | - - - - + * - - - |
Int: |-----------------| |------------------|
1 2
So in the other direction on the same number line:
Float: -3 .5 -2 .5 -1
-2.6
| - - - * + - - - - | - - - - + - - - - |
Int: |-----------------| |-----------------|
-3 -2
Or think of it like this: -2.6 is the same offset from -3 as +2.4 is
from 2. In other words, -2.6 and 2.4 are in the same realative postion
from the lower integral point. (Is there a better word for that?)
>
> I don't know about c/c++, but this behaviour is explicitly documented
> for Perl's int():
Actually this behavior is present in C and C++. It's just the way
integer division works internally. It effectively rounds towards 0
instead of down to the lower end of the integer on the number line.
I've never quite understood why it's like it is, in C and C++, one of
side effects is the irregular (from a math perspective) behavior of the
modulus operator (%.)
I agree that it's nice that Perl's % operator does not suffer from this
mathematical short coming. ;-)
| |
| Alan J. Flavell 2005-02-24, 8:57 pm |
| On Thu, 24 Feb 2005, Ala Qumsieh wrote:
> A. Sinan Unur wrote:
>
Was that typo supposed to be "mite" or "mighty" ?
[color=darkred]
> I have read earlier posts from others pointing out that your
> comments can be a bit harsh sometimes, and I agree with them. Your
> reply here seems to me too condescending and uncalled for.
Well, I feel motivated to support A.S.U here. I find the tendency to
report every trivial problem as "bug in ..." - without apparent
reference to any documentation - to be extremely rude and
counterproductive. I really would like to see an emphatic form of
words as a response to dissuade people from doing that, given that it
brings the whole business of bug reporting into disrepute.
And, by the way, makes it that much harder for the occasions when a
/real/ bug has been discovered, since it has habituated developers
into the belief that "bug report" almost certainly means "idiot who
can't be bothered to check the documentation".
IMHO and YMMV
| |
|
| A. Sinan Unur wrote:
> Ala Qumsieh <notvalid@email.com> wrote in
> news:X_rTd.9055$Pz7.3342@newssvr13.news.prodigy.com:
>
>
> I don't know on this one. I think the "I don't need to read what a
> function really does, if it does not do what I expect" attitude is
> quite irritating. Incidentally, this is not a rare attitude. See Jill
> Krugmann's post today.
I think I was a little missleading then, and I'm sorry. I knew that int
does what it does. What I was really getting at was why laguages like
Perl, c, c++, etc, do this sort of division in the first place?
I merely posted out of curiosity, to make a healthy discussion and learn
something I didn't know about this subject.
I also remember reading math books in the past (I'll post if I can find
them) that agree with the notion I put forth, that int(-2.6) = -3, (not
I mean 'int' in a general context, not Perl's 'int()') which is what
should happen for a modulus to work correctly, for example, to yield 2
if mod(-13, 5). If you round towards 0, you get -3 from that. A negative
remainder doesn't seme to make any sence in math afaik.
:> Snail
| |
| Ala Qumsieh 2005-02-24, 8:57 pm |
| A. Sinan Unur wrote:
> On the other hand, I do value your opinion of me, so I'll have to figure
> something out.
Thanks. I'm glad you took it this way.
--Ala
PS. I have been accused of similar behavior in the past, so you're in
good company ;)
| |
|
| Alan J. Flavell wrote:
> On Thu, 24 Feb 2005, Ala Qumsieh wrote:
>
>
> Was that typo supposed to be "mite" or "mighty" ?
>
>
> Well, I feel motivated to support A.S.U here. I find the tendency to
> report every trivial problem as "bug in ..." - without apparent
> reference to any documentation - to be extremely rude and
> counterproductive.
My aplogies. I realize my subject line was very poorly choosen. I did
not intend on coming out as rude. I only wanted to start a dicussion on
why langs like Perl, c, c++ (and java?) do this sort of division. I am
thinking there has to be some logical reason why languages to this.
:> Snail
| |
| Alan J. Flavell 2005-02-25, 3:58 am |
| On Thu, 24 Feb 2005, Snail wrote:
>
> My aplogies. I realize my subject line was very poorly choosen. I
> did not intend on coming out as rude.
Thank you for this response.
> I only wanted to start a dicussion on why langs like Perl, c, c++
> (and java?) do this sort of division.
I personally would favour an unbiased algorithm, rather than one which
has twice the range of numbers yielding zero as yield any other
integer value. But the important thing is to check the documentation.
all the best
| |
| brian d foy 2005-02-25, 3:58 am |
| In article <cvleei$on4$1@news.astound.net>, Snail <snail@localhost.com>
wrote:
> Why is this:
>
> $ perl -e 'print (int (-2.6), "\n")'
> -2
>
> Shouldn't it be -3? I thought converting from float to int is supposed
> to give the integer part, which is -3, and not round towards zero,
The docs for int() specifically say that it truncates towards zero.
That works no matter which side of zero you are on.
In my mind, it doesn't think about number lines. It just takes the
digits in the integer portion and discards anything after the
decimal place. It's not that it's supposed to do anything, as long
as it does what the author said he wanted it to do. It's not
a bug if it's doing what it's documented to do.
If you need something else else, you can write it yourself.
--
brian d foy, comdog@panix.com
Subscribe to The Perl Review: http://www.theperlreview.com
| |
| John W. Kennedy 2005-02-25, 3:58 am |
| Snail wrote:
> Why is this:
>
> $ perl -e 'print (int (-2.6), "\n")'
> -2
>
> Shouldn't it be -3? I thought converting from float to int is supposed
> to give the integer part, which is -3, and not round towards zero, as it
> seems to be doing, resulting in -2? For that matter, why does c/c++ do
> this too?
>
> Any hand calculator I've tried gives -3 for int (-2.6), like a texas
> instruments graphing calc.
>
> To it's credit, perl correctly does mod func correctly:
>
> $ perl -e 'print (-13 % 5, "\n")'
> 2
>
> Where as in c/c++ you get -3, which is mathematically incorrect. (Any
> hand calculator I've tried gives 2 for the above operation.)
Actually, C doesn't define the results of / and % unless both arguments
are positive. It's up to the compiler writer (which typically means it's
up to the hardware architect's design for the "divide" opcode). So Perl
is better defined than C in this respect. (However, when under the
control of "use integer;", Perl works like C.)
There are a gazillion programming languages and dialects out there, and
nearly as many different ways of addressing the noninteger-to-integer
problem. Be glad that Perl at least defines what "int" means; some
languages in the past have regarded it as an "implementation detail".
---
John W. Kennedy
"Give up vows and dogmas, and fixed things, and you may grow like That.
....you may come to think a blow bad, because it hurts, and not because
it humiliates. You may come to think murder wrong, because it is
violent, and not because it is unjust."
-- G. K. Chesterton. "The Ball and the Cross"
| |
| A. Sinan Unur 2005-02-25, 3:58 am |
| "Snail" <snail@localhost.com> wrote in news:cvllsb$sai$1@news.astound.net:
> My aplogies. I realize my subject line was very poorly choosen.
I want to join Alan in thanking you for this response. I did misinterpret
your intentions based on previous experience, and I apologize for that
response.
Sinan
| |
|
| Alan J. Flavell wrote:
> On Thu, 24 Feb 2005, Snail wrote:
>
>
> Thank you for this response.
Your very welcome.
>
> I personally would favour an unbiased algorithm, rather than one which
> has twice the range of numbers yielding zero as yield any other
> integer value. But the important thing is to check the documentation.
Great point. I guess it's a matter of looking at it but this is a great
way of comparing the outcomes on the negative side of zero.
> all the best
You too.
:> Snail
| |
| Anno Siegel 2005-02-25, 8:58 am |
| Alfred Z. Newmane <a.newmane.remove@eastcoastcz.com> wrote in comp.lang.perl.misc:
> darkon wrote:
>
> Not mathematically it isn't.
Mathematics is what mathematicians define it to be.
In particular, the int function is rarely used in mathematics (the
floor and ceiling functions are). There is no binding convention
how it would have to be defined.
> I should be -3. Think of it like this. The
> int part of 2.6 is 2, which is the /lowest/ number before the next
^^^^^^^
highest
> integer on the number line. Applying this to -2.6, the /lowest/ number
> before the next integer is -3.
It is also the integer whose absolute value is maximal below or equal
to (the absolute value of) 2.6. Apply that to -2.6, and the result is -3.
Anno
| |
| Ilya Zakharevich 2005-02-25, 8:58 am |
| [A complimentary Cc of this posting was sent to
Snail
<snail@localhost.com>], who wrote in article <cvllkr$s7v$1@news.astound.net>:
> I think I was a little missleading then, and I'm sorry. I knew that int
> does what it does. What I was really getting at was why laguages like
> Perl, c, c++, etc, do this sort of division in the first place?
I have no idea why C had chosen this (IMO, completely broken) semantic
of convert-to-integer. But since C did it, so should have C++.
Now why Perl did it? Before about v5.005, Perl was just a very
shallow wrapper about C w.r.t. numeric stuff. And when I got bold
enough to change the semantic of numerics, the backward compatibility
stroke in. One of arguments (IIRC, by tchrist) was that the code like
my $digit = int random 10;
was a legitimate Perl, so it would not be very nice to suddently make
it produce 10 as a possible answer.
Hope this helps,
Ilya
| |
| Arndt Jonasson 2005-02-25, 8:58 am |
|
"Snail" <snail@localhost.com> writes:
> [...]
> I only wanted to start a dicussion on
> why langs like Perl, c, c++ (and java?) do this sort of division. I am
> thinking there has to be some logical reason why languages to this.
I think comp.programming may be the right group for this, but I haven't
read it for a long time, so I don't know if it's still a useful group.
I'm sure the question has been asked many times in comp.lang.c, and I
would be surprised if Chris Torek hasn't given an excellent answer at
some time.
C++ inherited the C semantics, of course. Perl maybe took the C semantics
because C was the predominant language in the environment where Perl
was developed (but this is speculation on my part).
For some languages, all the relevant functions exist: truncating upward,
downward and towards zero. The former are often called 'ceiling' and
'floor' when they exist.
It's also historically ill-defined what a 'mod' function does when its
second argument is negative. I think that C, at least originally, took
the view that the C 'mod' operator ('%') did whatever the processor
instruction did, which was the expected thing for positive
arguments, and something you should not rely upon for negative arguments.
I don't know what the most recent C standard says about the subject.
| |
| Robert Sedlacek 2005-02-25, 8:58 am |
| Snail wrote:
> Any hand calculator I've tried gives -3 for int (-2.6), like a texas
> instruments graphing calc.
If you're looking for that, you may give the POSIX package a chance, I
think there were rounding functions. hth.
--
http://www.dunkelheit.at/
The first rule of project mayhem is: you do not ask questions.
-- Fight Club
| |
|
| On Thu, 24 Feb 2005 12:46:47 -0800, "Snail" <snail@localhost.com>
wrote:
>Why is this:
>
>$ perl -e 'print (int (-2.6), "\n")'
>-2
>
>Shouldn't it be -3? I thought converting from float to int is supposed
>to give the integer part, which is -3, and not round towards zero, as it
>seems to be doing, resulting in -2? For that matter, why does c/c++ do
>this too?
>
>Any hand calculator I've tried gives -3 for int (-2.6), like a texas
>instruments graphing calc.
>
>To it's credit, perl correctly does mod func correctly:
>
>$ perl -e 'print (-13 % 5, "\n")'
>2
>
>Where as in c/c++ you get -3, which is mathematically incorrect. (Any
>hand calculator I've tried gives 2 for the above operation.)
>
There is no int() function in C.
One may _cast_ a float to an int, but this is not a function call.
The effects of this are platform and implementation dependent per the
standard. This was due to the history of C from it's inception.
Here's what the ANSI C documentation has to say:
"When an object of floating type is converted to an integral type, the
fractional part is truncated. No rounding takes place in the
conversion process."
The ANSI, <float.h> was an attempt to characterize the
implementation-dependent behavior of the floating point types so that
a coder could detect at compile time the nature of the environment and
avoid errors. Likewise, <limits.h> was an attempt to characterize the
integral types.
For example, in Perl what would happen if you performed int(-33000.0)?
According to C's <limits.h> INT_MIN is -32767, unless Perl
automatically converts it to a long, the result should be an error. If
it silently converts it to a long how will the program behave if what
the programmer presumes is an int is used in a bitmap context?
In C++ it is the designer of the class who determines the behavior of
the operator. A proper numeric class might have an int operator that
takes the integer part of a floating type and a round operator that
rounds a float to the nearest integer.
|
|
|
|
|