Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #46060 > unrolled thread
| Started by | Ahmed Abdulshafy <abdulshafy@gmail.com> |
|---|---|
| First post | 2013-05-26 04:11 -0700 |
| Last post | 2013-05-27 21:36 -0400 |
| Articles | 20 on this page of 71 — 22 participants |
Back to article view | Back to comp.lang.python
Short-circuit Logic Ahmed Abdulshafy <abdulshafy@gmail.com> - 2013-05-26 04:11 -0700
Re: Short-circuit Logic Roy Smith <roy@panix.com> - 2013-05-26 07:38 -0400
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-26 12:13 +0000
Re: Short-circuit Logic Ahmed Abdulshafy <abdulshafy@gmail.com> - 2013-05-27 13:11 -0700
Re: Short-circuit Logic Nobody <nobody@nowhere.com> - 2013-05-28 01:10 +0100
Re: Short-circuit Logic Ahmed Abdulshafy <abdulshafy@gmail.com> - 2013-05-28 01:39 -0700
RE: Short-circuit Logic Carlos Nepomuceno <carlosnepomuceno@outlook.com> - 2013-05-28 12:32 +0300
Re: Short-circuit Logic Mark Lawrence <breamoreboy@yahoo.co.uk> - 2013-05-28 12:45 +0100
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-28 13:51 +0000
Re: Short-circuit Logic Grant Edwards <invalid@invalid.invalid> - 2013-05-28 15:14 +0000
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-28 15:55 +0000
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-28 13:48 +0000
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-29 00:01 +1000
Re: Short-circuit Logic Ahmed Abdulshafy <abdulshafy@gmail.com> - 2013-05-29 07:27 -0700
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-30 00:32 +1000
Re: Short-circuit Logic rusi <rustompmody@gmail.com> - 2013-05-29 07:33 -0700
Re: Short-circuit Logic Ian Kelly <ian.g.kelly@gmail.com> - 2013-05-29 10:50 -0600
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-30 02:28 +0000
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-30 13:45 +1000
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-30 05:42 +0000
Re: Short-circuit Logic Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2013-05-30 10:22 +0300
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-30 08:29 +0000
Re: Short-circuit Logic Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2013-05-30 12:07 +0300
Re: Short-circuit Logic Nobody <nobody@nowhere.com> - 2013-05-30 23:55 +0100
Re: Short-circuit Logic Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-05-30 19:31 -0400
Re: Short-circuit Logic Stefan Drees <stefan@drees.name> - 2013-05-31 17:34 +0200
Re: Short-circuit Logic Roy Smith <roy@panix.com> - 2013-05-30 08:48 -0400
Re: Short-circuit Logic Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-05-30 19:38 -0400
Re: Short-circuit Logic Nobody <nobody@nowhere.com> - 2013-05-31 02:10 +0100
Re: Short-circuit Logic Roy Smith <roy@panix.com> - 2013-05-30 21:21 -0400
Re: Short-circuit Logic Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-05-30 21:57 -0400
Re: Short-circuit Logic Michael Torrie <torriem@gmail.com> - 2013-05-30 21:33 -0600
RE: Short-circuit Logic Carlos Nepomuceno <carlosnepomuceno@outlook.com> - 2013-05-31 03:03 +0300
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-30 18:29 +1000
RE: Short-circuit Logic Carlos Nepomuceno <carlosnepomuceno@outlook.com> - 2013-05-31 00:03 +0300
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-31 05:13 +0000
RE: Short-circuit Logic Carlos Nepomuceno <carlosnepomuceno@outlook.com> - 2013-05-31 09:42 +0300
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-31 08:11 +0000
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-31 17:09 +1000
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-31 08:45 +0000
Re: Short-circuit Logic Roy Smith <roy@panix.com> - 2013-05-31 09:20 -0400
RE: Short-circuit Logic Carlos Nepomuceno <carlosnepomuceno@outlook.com> - 2013-06-01 10:23 +0300
Re: Short-circuit Logic 88888 Dihedral <dihedral88888@gmail.com> - 2013-05-30 20:11 -0700
Re: Short-circuit Logic Dave Angel <davea@davea.name> - 2013-05-29 20:23 -0400
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-30 05:20 +0000
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-30 05:10 +0000
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-30 15:22 +1000
Re: Short-circuit Logic Roy Smith <roy@panix.com> - 2013-05-30 08:40 -0400
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-30 22:58 +1000
Re: Short-circuit Logic rusi <rustompmody@gmail.com> - 2013-05-30 09:58 -0700
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-31 03:23 +1000
Re: Short-circuit Logic Rick Johnson <rantingrickjohnson@gmail.com> - 2013-05-30 17:13 -0700
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-31 12:29 +1000
Re: Short-circuit Logic Ethan Furman <ethan@stoneleaf.us> - 2013-05-30 08:02 -0700
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-31 01:56 +1000
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-30 16:40 +0000
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-30 19:22 +0000
Re: Short-circuit Logic Chris Angelico <rosuav@gmail.com> - 2013-05-31 07:46 +1000
Re: Short-circuit Logic Ethan Furman <ethan@stoneleaf.us> - 2013-05-30 09:30 -0700
Re: Short-circuit Logic Neil Cerutti <neilc@norwich.edu> - 2013-05-30 19:30 +0000
Re: Short-circuit Logic Ian Kelly <ian.g.kelly@gmail.com> - 2013-05-30 13:49 -0600
Re: Short-circuit Logic Terry Jan Reedy <tjreedy@udel.edu> - 2013-05-26 16:19 -0400
Re: Short-circuit Logic Roy Smith <roy@panix.com> - 2013-05-26 16:22 -0400
Re: Short-circuit Logic Terry Jan Reedy <tjreedy@udel.edu> - 2013-05-26 17:28 -0400
Re: Short-circuit Logic Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-05-27 00:40 +0000
Re: Short-circuit Logic Cameron Simpson <cs@zip.com.au> - 2013-05-27 11:57 +1000
Re: Short-circuit Logic rusi <rustompmody@gmail.com> - 2013-05-26 21:44 -0700
Re: Short-circuit Logic Vito De Tullio <vito.detullio@gmail.com> - 2013-05-27 06:59 +0200
Re: Short-circuit Logic Nobody <nobody@nowhere.com> - 2013-05-27 18:52 +0100
Re: Short-circuit Logic Ahmed Abdulshafy <abdulshafy@gmail.com> - 2013-05-27 13:08 -0700
Re: Short-circuit Logic Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-05-27 21:36 -0400
Page 1 of 4 [1] 2 3 4 Next page →
| From | Ahmed Abdulshafy <abdulshafy@gmail.com> |
|---|---|
| Date | 2013-05-26 04:11 -0700 |
| Subject | Short-circuit Logic |
| Message-ID | <5f101d70-e51f-4531-9153-c92ee2486fd9@googlegroups.com> |
Hi,
I'm having a hard time wrapping my head around short-circuit logic that's used by Python, coming from a C/C++ background; so I don't understand why the following condition is written this way!>
if not allow_zero and abs(x) < sys.float_info.epsilon:
print("zero is not allowed")
The purpose of this snippet is to print the given line when allow_zero is False and x is 0.
[toc] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2013-05-26 07:38 -0400 |
| Message-ID | <roy-370944.07383826052013@news.panix.com> |
| In reply to | #46060 |
In article <5f101d70-e51f-4531-9153-c92ee2486fd9@googlegroups.com>,
Ahmed Abdulshafy <abdulshafy@gmail.com> wrote:
> Hi,
> I'm having a hard time wrapping my head around short-circuit logic that's
> used by Python, coming from a C/C++ background; so I don't understand why the
> following condition is written this way!>
>
> if not allow_zero and abs(x) < sys.float_info.epsilon:
> print("zero is not allowed")
>
> The purpose of this snippet is to print the given line when allow_zero is
> False and x is 0.
I don't understand your confusion. Short-circuit evaluation works in
Python exactly the same way it works in C. When you have a boolean
operation, the operands are evaluated left-to-right, and evaluation
stops as soon as the truth value of the expression is known.
In C, you would write:
if (p && p->foo) {
blah();
}
to make sure that you don't dereference a null pointer. A similar
example in Python might be:
if d and d["foo"]:
blah()
which protects against trying to access an element of a dictionary if
the dictionary is None (which might happen if d was an optional argument
to a method and wasn't passed on this invocation).
But, none of that applies to your example. The condition is
not allow_zero and abs(x) < sys.float_info.epsilon:
it's safe to evaluate "abs(x) < sys.float_info.epsilon" no matter what
the value of "not allow_zero". For the purposes of understanding your
code, you can pretend that short-circuit evaluation doesn't exist!
So, what is your code doing that you don't understand?
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-05-26 12:13 +0000 |
| Message-ID | <51a1fc7b$0$30002$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #46060 |
On Sun, 26 May 2013 04:11:56 -0700, Ahmed Abdulshafy wrote:
> Hi,
> I'm having a hard time wrapping my head around short-circuit logic
> that's used by Python, coming from a C/C++ background; so I don't
> understand why the following condition is written this way!
>
> if not allow_zero and abs(x) < sys.float_info.epsilon:
> print("zero is not allowed")
Follow the logic.
If allow_zero is a true value, then "not allow_zero" is False, and the
"and" clause cannot evaluate to true. (False and X is always False.) So
print is not called.
If allow_zero is a false value, then "not allow_zero" is True, and the
"and" clause depends on the second argument. (True and X is always X.) So
abs(x) < sys.float_info.epsilon is tested, and if that is True, print is
called.
By the way, I don't think much of this logic. Values smaller than epsilon
are not necessarily zero:
py> import sys
py> epsilon = sys.float_info.epsilon
py> x = epsilon/10000
py> x == 0
False
py> x * 3 == 0
False
py> x + epsilon == 0
False
py> x + epsilon == epsilon
False
The above logic throws away many perfectly good numbers and treats them
as zero even though they aren't.
> The purpose of this snippet is to print the given line when allow_zero
> is False and x is 0.
Then the snippet utterly fails at that, since it prints the line for many
values of x which can be distinguished from zero. The way to test whether
x equals zero is:
x == 0
What the above actually tests for is whether x is so small that (1.0+x)
cannot be distinguished from 1.0, which is not the same thing. It is also
quite arbitrary. Why 1.0? Why not (0.0001+x)? Or (0.00000001+x)? Or
(10000.0+x)?
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Ahmed Abdulshafy <abdulshafy@gmail.com> |
|---|---|
| Date | 2013-05-27 13:11 -0700 |
| Message-ID | <2abf4e9c-8c3b-4e2f-80c9-50c1f1d75c9d@googlegroups.com> |
| In reply to | #46065 |
On Sunday, May 26, 2013 2:13:47 PM UTC+2, Steven D'Aprano wrote:
> On Sun, 26 May 2013 04:11:56 -0700, Ahmed Abdulshafy wrote:
>
>
>
> > Hi,
>
> > I'm having a hard time wrapping my head around short-circuit logic
>
> > that's used by Python, coming from a C/C++ background; so I don't
>
> > understand why the following condition is written this way!
>
> >
>
> > if not allow_zero and abs(x) < sys.float_info.epsilon:
>
> > print("zero is not allowed")
>
>
>
> Follow the logic.
>
>
>
> If allow_zero is a true value, then "not allow_zero" is False, and the
>
> "and" clause cannot evaluate to true. (False and X is always False.) So
>
> print is not called.
>
>
>
> If allow_zero is a false value, then "not allow_zero" is True, and the
>
> "and" clause depends on the second argument. (True and X is always X.) So
>
> abs(x) < sys.float_info.epsilon is tested, and if that is True, print is
>
> called.
>
>
>
> By the way, I don't think much of this logic. Values smaller than epsilon
>
> are not necessarily zero:
>
>
>
> py> import sys
>
> py> epsilon = sys.float_info.epsilon
>
> py> x = epsilon/10000
>
> py> x == 0
>
> False
>
> py> x * 3 == 0
>
> False
>
> py> x + epsilon == 0
>
> False
>
> py> x + epsilon == epsilon
>
> False
>
>
>
> The above logic throws away many perfectly good numbers and treats them
>
> as zero even though they aren't.
>
>
>
>
>
> > The purpose of this snippet is to print the given line when allow_zero
>
> > is False and x is 0.
>
>
>
> Then the snippet utterly fails at that, since it prints the line for many
>
> values of x which can be distinguished from zero. The way to test whether
>
> x equals zero is:
>
>
>
> x == 0
>
>
>
> What the above actually tests for is whether x is so small that (1.0+x)
>
> cannot be distinguished from 1.0, which is not the same thing. It is also
>
> quite arbitrary. Why 1.0? Why not (0.0001+x)? Or (0.00000001+x)? Or
>
> (10000.0+x)?
>
>
>
>
>
>
>
> --
>
> Steven
That may be true for integers, but for floats, testing for equality is not always precise
[toc] | [prev] | [next] | [standalone]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2013-05-28 01:10 +0100 |
| Message-ID | <pan.2013.05.28.00.10.04.235000@nowhere.com> |
| In reply to | #46221 |
On Mon, 27 May 2013 13:11:28 -0700, Ahmed Abdulshafy wrote: > On Sunday, May 26, 2013 2:13:47 PM UTC+2, Steven D'Aprano wrote: > >> What the above actually tests for is whether x is so small that (1.0+x) >> cannot be distinguished from 1.0, which is not the same thing. It is >> also quite arbitrary. Why 1.0? Why not (0.0001+x)? Or (0.00000001+x)? >> Or (10000.0+x)? > > That may be true for integers, What may be true for integers? > but for floats, testing for equality is not always precise And your point is? What Steven wrote is entirely correct: sys.float_info.epsilon is the smallest value x such that 1.0 and 1.0+x have distinct floating-point representations. It has no relevance for comparing to zero.
[toc] | [prev] | [next] | [standalone]
| From | Ahmed Abdulshafy <abdulshafy@gmail.com> |
|---|---|
| Date | 2013-05-28 01:39 -0700 |
| Message-ID | <48a99056-fa56-4352-b8b4-f52d3467ac96@googlegroups.com> |
| In reply to | #46233 |
On Tuesday, May 28, 2013 2:10:05 AM UTC+2, Nobody wrote: > On Mon, 27 May 2013 13:11:28 -0700, Ahmed Abdulshafy wrote: > > > > > On Sunday, May 26, 2013 2:13:47 PM UTC+2, Steven D'Aprano wrote: > > > > > >> What the above actually tests for is whether x is so small that (1.0+x) > > >> cannot be distinguished from 1.0, which is not the same thing. It is > > >> also quite arbitrary. Why 1.0? Why not (0.0001+x)? Or (0.00000001+x)? > > >> Or (10000.0+x)? > > > > > > That may be true for integers, > > > > What may be true for integers? > > > > > but for floats, testing for equality is not always precise > > > > And your point is? > > > > What Steven wrote is entirely correct: sys.float_info.epsilon is the > > smallest value x such that 1.0 and 1.0+x have distinct floating-point > > representations. It has no relevance for comparing to zero. He just said that the way to test for zero equality is x == 0, and I meant that this is true for integers but not necessarily for floats. And that's not specific to Python.
[toc] | [prev] | [next] | [standalone]
| From | Carlos Nepomuceno <carlosnepomuceno@outlook.com> |
|---|---|
| Date | 2013-05-28 12:32 +0300 |
| Message-ID | <mailman.2290.1369733548.3114.python-list@python.org> |
| In reply to | #46268 |
---------------------------------------- > Date: Tue, 28 May 2013 01:39:09 -0700 > Subject: Re: Short-circuit Logic > From: abdulshafy@gmail.com [...] >> What Steven wrote is entirely correct: sys.float_info.epsilon is the >> >> smallest value x such that 1.0 and 1.0+x have distinct floating-point >> >> representations. It has no relevance for comparing to zero. > > He just said that the way to test for zero equality is x == 0, and I meant that this is true for integers but not necessarily for floats. And that's not specific to Python. Have you read [1]? There's a section "Infernal Zero" that discuss this problem. I think it's very interesting to know! ;) Just my 49.99999999999998¢! lol [1] http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
[toc] | [prev] | [next] | [standalone]
| From | Mark Lawrence <breamoreboy@yahoo.co.uk> |
|---|---|
| Date | 2013-05-28 12:45 +0100 |
| Message-ID | <mailman.2293.1369741519.3114.python-list@python.org> |
| In reply to | #46268 |
On 28/05/2013 09:39, Ahmed Abdulshafy wrote: > > And that's not specific to Python. > Using google products is also not specific to Python. However whereever it's used it's a PITA as people are forced into reading double spaced crap. Please check out the link in my signature. -- If you're using GoogleCrap™ please read this http://wiki.python.org/moin/GoogleGroupsPython. Mark Lawrence
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-05-28 13:51 +0000 |
| Message-ID | <51a4b669$0$29966$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #46268 |
On Tue, 28 May 2013 01:39:09 -0700, Ahmed Abdulshafy wrote:
> He just said that the way to test for zero equality is x == 0, and I
> meant that this is true for integers but not necessarily for floats. And
> that's not specific to Python.
Can you show me a value of x where x == 0.0 returns False, but x actually
isn't zero?
Built-in floats only, if you subclass you can do anything you like:
class Cheating(float):
def __eq__(self, other):
return False
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Grant Edwards <invalid@invalid.invalid> |
|---|---|
| Date | 2013-05-28 15:14 +0000 |
| Message-ID | <ko2hjr$i4q$2@reader1.panix.com> |
| In reply to | #46287 |
On 2013-05-28, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
> On Tue, 28 May 2013 01:39:09 -0700, Ahmed Abdulshafy wrote:
>
>> He just said that the way to test for zero equality is x == 0, and I
>> meant that this is true for integers but not necessarily for floats. And
>> that's not specific to Python.
>
> Can you show me a value of x where x == 0.0 returns False, but x actually
> isn't zero?
I'm confused. Don't all non-zero values satisfy your conditions?
>>> x = 1.0
>>> x == 0.0
False
>>> x is 0.0
False
--
Grant Edwards grant.b.edwards Yow! I'm dressing up in
at an ill-fitting IVY-LEAGUE
gmail.com SUIT!! Too late...
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-05-28 15:55 +0000 |
| Message-ID | <51a4d37e$0$29966$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #46294 |
On Tue, 28 May 2013 15:14:03 +0000, Grant Edwards wrote: > On 2013-05-28, Steven D'Aprano <steve+comp.lang.python@pearwood.info> > wrote: >> On Tue, 28 May 2013 01:39:09 -0700, Ahmed Abdulshafy wrote: >> >>> He just said that the way to test for zero equality is x == 0, and I >>> meant that this is true for integers but not necessarily for floats. >>> And that's not specific to Python. >> >> Can you show me a value of x where x == 0.0 returns False, but x >> actually isn't zero? > > I'm confused. Don't all non-zero values satisfy your conditions? Of course they do :-( I meant "but x actually *is* zero". Sorry for the confusion. I blame the terrists. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-05-28 13:48 +0000 |
| Message-ID | <51a4b5a1$0$29966$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #46221 |
On Mon, 27 May 2013 13:11:28 -0700, Ahmed Abdulshafy wrote: > That may be true for integers, but for floats, testing for equality is > not always precise Incorrect. Testing for equality is always precise, and exact. The problem is not the *equality test*, but that you don't always have the number that you think you have. The problem lies elsewhere, not equality! Unfortunately, people who say "never test floats for equality" have misdiagnosed the problem, or they are giving a simple work-around which can be misleading to those who don't understand what is actually going on. Any floating point libraries that support IEEE-754 semantics can guarantee a few things, including: x == 0.0 if, and only if, x actually equals zero. This was not always the case for all floating point systems prior to IEEE-754. In his forward to the Apple Numerics Manual, William Kahan describes a Capriciously Designed Computer where 1/x can give a Division By Zero error even though x != 0. Fortunately, if you are programming in Python on Intel-compatible hardware, you do not have to worry about nightmares like that. Let me repeat that: in Python, you can trust that if x == 0.0 returns False, then x is definitely not zero. In any case, the test that you show is not a good test. I have already shown that it wrongly treats many non-zero numbers which can be distinguished from zero as if they were zero. But worse, it also fails as a guard against numbers which cannot be distinguished from zero! py> import sys py> epsilon = sys.float_info.epsilon py> x < epsilon # Is x so tiny it looks like zero? False py> y = 1e17 + x # x is not zero, so y should be > 1e17 py> 1/(1e17 - y) Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: float division by zero So as you can see, testing for "zero" by comparing to machine epsilon does not save you from Zero Division errors. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-05-29 00:01 +1000 |
| Message-ID | <mailman.2298.1369749670.3114.python-list@python.org> |
| In reply to | #46286 |
On Tue, May 28, 2013 at 11:48 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> py> y = 1e17 + x # x is not zero, so y should be > 1e17
> py> 1/(1e17 - y)
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> ZeroDivisionError: float division by zero
You don't even need to go for 1e17. By definition:
>>> sys.float_info.epsilon+1.0==1.0
False
>>> sys.float_info.epsilon+2.0==2.0
True
Therefore the same can be done with 2 as you did with 1e17.
>>> y = 2 + sys.float_info.epsilon
>>> 1/(2-y)
Traceback (most recent call last):
File "<pyshell#182>", line 1, in <module>
1/(2-y)
ZeroDivisionError: float division by zero
Of course, since we're working with a number greater than epsilon, we
need to go a little further, but we can still work with small numbers:
>>> x = sys.float_info.epsilon * 2 # Definitely greater than epsilon
>>> y = 4 + x
>>> 1/(4-y)
Traceback (most recent call last):
File "<pyshell#191>", line 1, in <module>
1/(4-y)
ZeroDivisionError: float division by zero
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ahmed Abdulshafy <abdulshafy@gmail.com> |
|---|---|
| Date | 2013-05-29 07:27 -0700 |
| Message-ID | <04b90c02-833a-4bad-88ad-ab71178b8f79@googlegroups.com> |
| In reply to | #46286 |
On Tuesday, May 28, 2013 3:48:17 PM UTC+2, Steven D'Aprano wrote: > On Mon, 27 May 2013 13:11:28 -0700, Ahmed Abdulshafy wrote: > > > > > That may be true for integers, but for floats, testing for equality is > > > not always precise > > > > Incorrect. Testing for equality is always precise, and exact. The problem > > is not the *equality test*, but that you don't always have the number > > that you think you have. The problem lies elsewhere, not equality! > > > Steven Well, this is taken from my python shell> >>> 0.33455857352426283 == 0.33455857352426282 True Anyway, man, those were not my words anyway, most programming books I've read state so. Here's an excerpt from the Python book, I'm currently reading> ">>> 0.0, 5.4, -2.5, 8.9e-4 (0.0, 5.4000000000000004, -2.5, 0.00088999999999999995) The inexactness is not a problem specific to Python—all programming languages have this problem with floating-point numbers."
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-05-30 00:32 +1000 |
| Message-ID | <mailman.2360.1369837963.3114.python-list@python.org> |
| In reply to | #46382 |
On Thu, May 30, 2013 at 12:27 AM, Ahmed Abdulshafy <abdulshafy@gmail.com> wrote: > Well, this is taken from my python shell> > >>>> 0.33455857352426283 == 0.33455857352426282 > True >>> 0.33455857352426283,0.33455857352426282 (0.3345585735242628, 0.3345585735242628) They're not representably different. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2013-05-29 07:33 -0700 |
| Message-ID | <48519aa0-d0cd-4ffc-a2f5-2107465321d8@qn4g2000pbc.googlegroups.com> |
| In reply to | #46382 |
On May 29, 7:27 pm, Ahmed Abdulshafy <abdulsh...@gmail.com> wrote: > On Tuesday, May 28, 2013 3:48:17 PM UTC+2, Steven D'Aprano wrote: > > On Mon, 27 May 2013 13:11:28 -0700, Ahmed Abdulshafy wrote: > > > > That may be true for integers, but for floats, testing for equality is > > > > not always precise > > > Incorrect. Testing for equality is always precise, and exact. The problem > > > is not the *equality test*, but that you don't always have the number > > > that you think you have. The problem lies elsewhere, not equality! > > > Steven > > Well, this is taken from my python shell> > > >>> 0.33455857352426283 == 0.33455857352426282 > > True > > Anyway, man, those were not my words anyway, most programming books I've read state so. Here's an excerpt from the Python book, I'm currently reading> > > ">>> 0.0, 5.4, -2.5, 8.9e-4 > (0.0, 5.4000000000000004, -2.5, 0.00088999999999999995) > > The inexactness is not a problem specific to Python—all programming languages have this problem with floating-point numbers." 0.0 == 0.0 implies 5.4 == 5.4 is not a true statement is what (I think) Steven is saying. 0 (or if you prefer 0.0) is special and is treated specially. Naturally if you reach (nearabout) 0.0 by some numerical process thats another matter...
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-05-29 10:50 -0600 |
| Message-ID | <mailman.2365.1369847746.3114.python-list@python.org> |
| In reply to | #46384 |
On Wed, May 29, 2013 at 8:33 AM, rusi <rustompmody@gmail.com> wrote: > 0.0 == 0.0 implies 5.4 == 5.4 > is not a true statement is what (I think) Steven is saying. > 0 (or if you prefer 0.0) is special and is treated specially. It has nothing to do with 0 being special. A floating point number will always equal itself (except for nan, which is even more special), and in particular 5.4 == 5.4. But if you have two different calculations that produce 0, or two different calculations that produce 5.4, you might actually get two different numbers that approximate 0 or 5.4 thanks to rounding error. If you then compare those two ever-so-slightly different numbers, you will find them unequal.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-05-30 02:28 +0000 |
| Message-ID | <51a6b969$0$29966$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #46394 |
On Wed, 29 May 2013 10:50:47 -0600, Ian Kelly wrote: > On Wed, May 29, 2013 at 8:33 AM, rusi <rustompmody@gmail.com> wrote: >> 0.0 == 0.0 implies 5.4 == 5.4 >> is not a true statement is what (I think) Steven is saying. 0 (or if >> you prefer 0.0) is special and is treated specially. > > It has nothing to do with 0 being special. A floating point number will > always equal itself (except for nan, which is even more special), and in > particular 5.4 == 5.4. But if you have two different calculations that > produce 0, or two different calculations that produce 5.4, you might > actually get two different numbers that approximate 0 or 5.4 thanks to > rounding error. If you then compare those two ever-so-slightly > different numbers, you will find them unequal. EXACTLY! The problem does not lie with the *equality operator*, it lies with the calculations. And that is an intractable problem -- in general, floating point is *hard*. So the problem occurs when we start with a perfectly good statement of the facts: "If you naively test the results of a calculation for equality without understanding what you are doing, you will often get surprising results" which then turns into a general heuristic that is often, but not always, reasonable: "In general, you should test for floating point *approximate* equality, in some appropriate sense, rather than exact equality" which then gets mangled to: "Never test floating point numbers for equality" and then implemented badly by people who have no clue what they are doing and have misunderstood the nature of the problem, leading to either: * de facto exact equality testing, only slower and with the *illusion* of avoiding equality, e.g. "abs(x-y) < sys.float_info.epsilon" is just a long and slow way of saying "x == y" when both numbers are sufficiently large; * incorrectly accepting non-equal numbers as "equal" just because they happen to be "close". The problem is that there is *no one right answer*, except "have everyone become an expert in floating point, then judge every case on its merits", which will never happen. But if nothing else, I wish that we can get past the rank superstition that you should "never" test floats for equality. That would be a step forward. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-05-30 13:45 +1000 |
| Message-ID | <mailman.2392.1369885517.3114.python-list@python.org> |
| In reply to | #46424 |
On Thu, May 30, 2013 at 12:28 PM, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > * de facto exact equality testing, only slower and with the *illusion* of > avoiding equality, e.g. "abs(x-y) < sys.float_info.epsilon" is just a > long and slow way of saying "x == y" when both numbers are sufficiently > large; > The problem here, I think, is that "epsilon" has two meanings: * sys.float_info.epsilon, which is an extremely specific value (the smallest x such that 1.0+x != x) * the mathematical concept, which is where the other got its name from. Let's suppose someone is told to compare floating point numbers by seeing if the absolute value of the difference is less than some epsilon. They look up "absolute value" and find abs(); they look up "epsilon" and think they've found it. Trouble is, they've found the wrong epsilon... and really, there's an engineering issue here too. Here's one of my favourite examples of equality comparisons: http://xkcd.com/1047/ # Let's say we measured this accurately to one part in 40 x = one_light_year_in_meters y = pow(99,8) x == y # False abs(x-y) < x/40 # True Measurement accuracy is usually far FAR worse than floating-point accuracy. It's pretty pointless to compare for some kind of "equality" that ignores this. Say you measure the diameter and circumference of a circle, accurate to one meter, and got values of 79 and 248; does this mean that pi is less than 3.14? No - in fact: pi = 248/79 # math.pi = 3.141592653589793 abs(pi-math.pi) < pi/79 # True Worst error is 1 in 79, so all comparisons are done with epsilon derived from that. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-05-30 05:42 +0000 |
| Message-ID | <51a6e6b8$0$11118$c3e8da3@news.astraweb.com> |
| In reply to | #46428 |
On Thu, 30 May 2013 13:45:13 +1000, Chris Angelico wrote: > Let's suppose someone is told to compare floating point numbers by > seeing if the absolute value of the difference is less than some > epsilon. Which is usually the wrong way to do it! Normally one would prefer *relative* error, not absolute: # absolute error: abs(a - b) < epsilon # relative error: abs(a - b)/a < epsilon One problem with absolute error is that it can give an entirely spurious image of "fuzziness", when in reality it is actually performing the same exact equality as == only slower and more verbosely. If a and b are sufficiently large, the smallest possible difference between a and b may be greater than epsilon (for whichever epsilon you pick). When that happens, you might as well just use == and be done with it. But using relative error also raises questions: - what if a is negative? - why relative to a instead of relative to b? - what if a is zero? The first, at least, is easy to solve: take the absolute value of a. But strangely, you rarely see programming books mention that, so I expect that there is a lot of code in the real world that assumes a is positive and does the wrong thing when it isn't. Here's another way, mathematically equivalent (although not necessarily equivalent using floating point computations!) which avoids the divide-by- zero problem: abs(a - b) < epsilon*a Whichever method you choose, there are gotchas to watch out for. > http://xkcd.com/1047/ Nice! -- Steven
[toc] | [prev] | [next] | [standalone]
Page 1 of 4 [1] 2 3 4 Next page →
Back to top | Article view | comp.lang.python
csiph-web