[Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Serhiy Storchaka
I searched usages of is_integer() on GitHub and have found that it is 
used *only* in silly code like (x/5).is_integer(), (x**0.5).is_integer() 
(or even (x**(1/3)).is_integer()) and in loops like:


   i = 0
   while i < 20:
   if i.is_integer():
   print(i)
   i += 0.1

(x/5).is_integer() is an awful way of determining the divisibility by 5. 
It returns wrong result for large integers and some floats. (x % 5 == 0) 
is a more clear and reliable way (or PEP 8 compliant (not x % 5)).


Does anybody know examples of the correct use of float.is_integer() in 
real programs? For now it looks just like a bug magnet. I suggest to 
deprecate it in 3.7 or 3.8 and remove in 3.9 or 3.10. If you even need 
to test if a float is an exact integer, you could use (not x % 1.0). It 
is even faster than x.is_integer().


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Chris Barker
On Wed, Mar 21, 2018 at 4:42 AM Steven D'Aprano  wrote:

>
>
> > Could float et al. add an __index__ method that would return a ValueError
> > if the value was not an integer?
>
> That would allow us to write things like:
>
> "abcdefgh"[5.0]
>
> which is one of the things __index__ was invented to prevent.


I’m not so sure — it was invented to prevent using e.g. 6.1 as an index,
which int(I) would allow.

More specifically, it was invented to Allow true integers that aren’t a
python int ( like numpy int types).

But, in fact, it is common to use floating point computation to compute an
index — though usually one would make a conscious choice between round()
and floor() and ceil() when doing so.

Passing floor(a_float) as an index is a perfectly reasonable thing to do.

But Guidos point is well taken — Having __index__ fail based on value is
setting people up for bugs down the line.

However, it seems use of is_integer() on a float is setting people up for
exactly the same sorts of bugs.

Another example is that pow() functions sometimes swap to an exact
> algorithm if the power is an int. There's no particular reason why
> x**n and x**n.0 ought to be different, but they are:
>
> py> 123**10
> 792594609605189126649
>
> py> 123**10.0
> 7.925946096051892e+20


I think this is exactly like the __index__ use case. If the exponent is a
literal, use what you mean. If the exponent is a computed float, then you
really don’t want a different result depending on whether the computed
value is exactly an integer or one ULP off.

The user should check/convert to an integer with a method appropriate to
the problem at hand.

If it wasn’t too heavyweight, it might be nice to have some sort of flag on
floats indicating whether they really ARE an integer, rather than happen to
be:

-Created from an integer literal
- created from an integer object
- result of floor(), ceil() or round()

Any others?

But that would be too heavyweight, and not that useful.

In short, is_integer() is an attractive nuisance.

-CHB

PS: for the power example, the “right” solution is to have two operators:
integer power and float power, like we do for float vs floor division. No,
it’s not worth it in this case, but having it be value dependent would be
worse than type dependent.







>
> On the other hand, some might argue that by passing 10.0 as the power, I
> am specifically requesting a float implementation and result. I don't
> wish to argue in favour of either position, but just to point out that
> it is sometimes reasonable to want to know whether a float represents an
> exact integer value or not.
>
>
>
> --
> Steve
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/chris.barker%40noaa.gov
>
-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Chris Barker
>
>
> Does anybody know examples of the correct use of float.is_integer() in
> real programs? For now it looks just like a bug magnet. I suggest to
> deprecate it in 3.7 or 3.8 and remove in 3.9 or 3.10.


+1

It really doesn’t appear to be the right solution for any problem.

-CHB
-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] What is the purpose of NEXT_BLOCK()?

2018-03-21 Thread Serhiy Storchaka
There is the NEXT_BLOCK() macro in compile.c. It creates a new block, 
creates an implicit jump from the current block to the new block, and 
sets it as the current block.


But why it is used? All seems working if remove NEXT_BLOCK(). If there 
was a need of NEXT_BLOCK() (if it reduces the computational complexity 
of compilation or allows some optimizations), it should be documented, 
and we should analyze the code and add missed NEXT_BLOCK() where they 
are needed, and perhaps add new tests. Otherwise it can be removed.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Nick Coghlan
On 14 March 2018 at 08:29, Tim Peters  wrote:

> [Tim]
> >> An obvious way to extend it is for Fraction() to look for a special
> >> method too, say "_as_integer_ratio()".
>
> [Greg Ewing]
> > Why not __as_integer_ratio__?
>
> Because. at this point, that would be beating a dead horse ;-)
>

I'm not so sure about that, as if we define a protocol method for it, then
we'd presumably also define an "operator.as_integer_ratio" function, and
that function could check __index__ in addition to checking the new
protocol method.

For example:

def as_integer_ratio(n):
# Automatically accept true integers
if hasattr(n, "__index__"):
return (n.__index__(), 1)
# New reserved protocol method
if hasattr(n, "__integer_ratio__"):
return n.__integer_ratio__()
# Historical public protocol method
if hasattr(n, "as_integer_ratio"):
return n.as_integer_ratio()
# Check for lossless integer conversion
try:
int_n = int(n)
except TypeError:
pass
else:
if int_n == n:
return (int_n, 1)
raise TypeError(f"{type(n)} does not support conversion to an
integer ratio")

Similarly, on the "operator.is_integer" front:

def is_integer(n):
# Automatically accept true integers
if hasattr(n, "__index__"):
return True
# New reserved protocol method
if hasattr(n, "__is_integer__"):
return n.__is_integer__()
# Historical public protocol method
if hasattr(n, "is_integer"):
return n.is_integer()
# As a last resort, check for lossless int conversion
return int(n) == n

Cheers,
Nick.

P.S. I've suggested "operator" as a possible location, since that's where
we put "operator.index", and it's a low level module that doesn't bring in
any transitive dependencies. However, putting these protocol wrappers
somewhere else (e.g. in "math" or "numbers") may also make sense.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Steven D'Aprano
On Wed, Mar 21, 2018 at 10:31:19AM +, Chris Barker wrote:
> On Wed, Mar 21, 2018 at 4:42 AM Steven D'Aprano  wrote:
> > > Could float et al. add an __index__ method that would return a ValueError
> > > if the value was not an integer?
> >
> > That would allow us to write things like:
> >
> > "abcdefgh"[5.0]
> >
> > which is one of the things __index__ was invented to prevent.
> 
> I’m not so sure — it was invented to prevent using e.g. 6.1 as an index,
> which int(I) would allow.

As would int(6.0). If we wanted 6.0 to be accepted as an index, then 
floats would already have an __index__ method :-)


[...]
> But Guidos point is well taken — Having __index__ fail based on value is
> setting people up for bugs down the line.
> 
> However, it seems use of is_integer() on a float is setting people up for
> exactly the same sorts of bugs.

I don't think so. You aren't going to stop people from testing whether a 
float is an integer. (And why should you? It isn't *wrong* to do so. 
Some floats simply are integer valued.) All you will do is force them to 
write code which is even worse than what they have now.

One wrong solution:

int(x) == x

That can raise ValueError and OverflowError, but at least it is somewhat 
understandable.

Serhiy suggested that people should use the cryptic:

(not x % 1.0)

but that's hardly self-documenting: its not obvious what it does or how 
it works. Suppose I see that snippet in a code review, and let's 
suppose I recognise it and aren't totally perplexed by it. Will it 
pass the review? I have to make a decision:

- will it fail when x is an INF or NAN?

- does it give the correct results when x is negative?

- does this suffer from rounding errors that could affect the result?

- what if x is not a float, but a Decimal, a Fraction or an int too 
  big to convert to a float?


None of the answers are obvious at a glance.

In fact, Serhiy's suggestion is not correct when x is not a float:

py> from fractions import Fraction
py> x =Fraction(1) + Fraction(1, 10**500)  # certainly not an integer
py> x.denominator == 1  # sadly Fraction doesn't support is_integer
False
py> not x % 1.0
True


> Another example is that pow() functions sometimes swap to an exact
> > algorithm if the power is an int. There's no particular reason why
> > x**n and x**n.0 ought to be different, but they are:
> >
> > py> 123**10
> > 792594609605189126649
> >
> > py> 123**10.0
> > 7.925946096051892e+20
> 
> 
> I think this is exactly like the __index__ use case. If the exponent is a
> literal, use what you mean.

Naturally. I already eluded to that in my earlier post. Nevertheless, 
this is just an example, and we shouldn't expect that the power will be 
a literal. I'm just illustrating the concept.


> If the exponent is a computed float, then you
> really don’t want a different result depending on whether the computed
> value is exactly an integer or one ULP off.

I don't think you actually mean to say that. I'm pretty sure that we 
*do* want different results if the exponent differs from an integer by 
one ULP. After all, that's what happens now:

py> x = 25
py> x**1.0
25.0
py> x**(1.0+(2**-52))  # one ULP above
25.018
py> x**(1.0-(2**-53))  # one ULP below
24.99


I don't want to change the behaviour of pow(), but we shouldn't dismiss 
the possibility of some other numeric function wanting to treat values 
N.0 and N the same. Let's say, an is_prime(x) function that supports 
floats as well as ints:

is_prime(3.0)  # True
is_prime(3.1)  # False

If the argument x.is_integer() returns True, then we convert to an int 
and test for primality. If not, then it's definitely not prime.


> The user should check/convert to an integer with a method appropriate to
> the problem at hand.

Oh, you mean something like x.is_integer()? I agree!

*wink*



> If it wasn’t too heavyweight, it might be nice to have some sort of flag on
> floats indicating whether they really ARE an integer, rather than happen to
> be:
> 
> -Created from an integer literal
> - created from an integer object
> - result of floor(), ceil() or round()

I don't understand this.

You seem to be saying that none of the following are "really" integer 
valued:

float(10)
floor(10.1)
ceil(10.1)
round(10.1)

If they're not all exactly equal to the integer 10, what on earth should 
they equal?



-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] ThreadedProcessPoolExecutor

2018-03-21 Thread Roberto Martínez
Hi,

I've made a custom concurrent.futures.Executor mixing the
ProcessPoolExecutor and ThreadPoolExecutor.

I've published it here:

https://github.com/nilp0inter/threadedprocess

This executor is very similar to a ProcessPoolExecutor, but each process in
the pool have it's own ThreadPoolExecutor inside.

The motivation for this executor is mitigate the problem we have in a
project were we have a very large number of long running IO bounded tasks,
that have to run concurrently. Those long running tasks have sparse CPU
bounded operations.

To resolve this problem I considered multiple solutions:

   1. Use asyncio to run the IO part as tasks and use a ProcessPoolExecutor
   to run the CPU bounded operations with "run_in_executor". Unfortunately the
   CPU operations depends on a large memory context, and using a
   ProcessPoolExecutor this way force the parent process to picklelize all the
   context to send it to the task, and because the context is so large, this
   operation is itself very CPU demanding. So it doesn't work.
   2. Executing the IO/CPU bounded operations in different processes with
   multiprocessing.Process. This actually works, but the number of idle
   processes in the system is too large, resulting in a bad memory footprint.
   3. Executing the IO/CPU bounded operations in threads. This doesn't work
   because the sum of all CPU operations saturate the core where the Python
   process is running and the other cores are wasted doing nothing.

So I coded the ThreadedProcessPoolExecutor that helped me maintaining the
number of processes under control (I just have one process per CPU core)
allowing me to have a very high concurrency (hundreds of threads per
process).

I have a couple of questions:

The first one is about the license. Given that I copied the majority of the
code from the concurrent.futures library, I understand that I have to
publish the code under the PSF LICENSE. Is this correct?

My second question is about the package namespace. Given that this is an
concurrent.futures.Executor subclass I understand that more intuitive place
to locate it is under concurrent.futures. Is this a suitable use case for
namespace packages? Is this a good idea?

Best regards,
Roberto
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Guido van Rossum
I searched 6M LoC of Python code at Dropbox and found only three uses. They
seem legit. Two are about formatting a number that's given as a float,
deciding whether to print a float as 42 or 3.14. The third is attempting a
conversion from float to integer where a non-integer must raise a specific
exception (the same function also supports a string as long as it can be
parsed as an int).

I don't doubt we would get by if is_integer() was deprecated.


On Wed, Mar 21, 2018 at 3:31 AM, Chris Barker  wrote:

>
>> Does anybody know examples of the correct use of float.is_integer() in
>> real programs? For now it looks just like a bug magnet. I suggest to
>> deprecate it in 3.7 or 3.8 and remove in 3.9 or 3.10.
>
>
> +1
>
> It really doesn’t appear to be the right solution for any problem.
>
> -CHB
> --
>
> Christopher Barker, Ph.D.
> Oceanographer
>
> Emergency Response Division
> NOAA/NOS/OR&R(206) 526-6959   voice
> 7600 Sand Point Way NE   (206) 526-6329   fax
> Seattle, WA  98115   (206) 526-6317   main reception
>
> chris.bar...@noaa.gov
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> guido%40python.org
>
>


-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] What is the purpose of NEXT_BLOCK()?

2018-03-21 Thread Guido van Rossum
Maybe spelunking in the Python 2 branch will help? It seems it was
introduced in 2005 by Jeremy Hylton with this comment:

/* The distinction between NEW_BLOCK and NEXT_BLOCK is subtle.  (I'd
   like to find better names.)  NEW_BLOCK() creates a new block and sets
   it as the current block.  NEXT_BLOCK() also creates an implicit jump
   from the current block to the new block.
*/

That comment (and NEW_BLOCK()) are no longer found in the Python 3 source.

On Wed, Mar 21, 2018 at 3:52 AM, Serhiy Storchaka 
wrote:

> There is the NEXT_BLOCK() macro in compile.c. It creates a new block,
> creates an implicit jump from the current block to the new block, and sets
> it as the current block.
>
> But why it is used? All seems working if remove NEXT_BLOCK(). If there was
> a need of NEXT_BLOCK() (if it reduces the computational complexity of
> compilation or allows some optimizations), it should be documented, and we
> should analyze the code and add missed NEXT_BLOCK() where they are needed,
> and perhaps add new tests. Otherwise it can be removed.
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/guido%
> 40python.org
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] ThreadedProcessPoolExecutor

2018-03-21 Thread Guido van Rossum
Roberto,

That looks like an interesting class. I presume you're intending to publish
this as a pip package on PyPI.python.org?

I'm no lawyer, but I believe you can license your code under a new license
(I recommend BSD) as long as you keep a copy and a mention of the PSF
license in your distribution as well. (Though perhaps you could structure
your code differently and inherit from the standard library modules rather
than copying them?)

In terms of the package namespace, do not put it in the same namespace as
standard library code! It probably won't work and will cause world-wide
pain and suffering for the users of your code. Invent your project name and
use that as a top-level namespace, like everyone else. :-)

Good luck with your project,

--Guido



On Wed, Mar 21, 2018 at 8:03 AM, Roberto Martínez <
robertomartin...@gmail.com> wrote:

> Hi,
>
> I've made a custom concurrent.futures.Executor mixing the
> ProcessPoolExecutor and ThreadPoolExecutor.
>
> I've published it here:
>
> https://github.com/nilp0inter/threadedprocess
>
> This executor is very similar to a ProcessPoolExecutor, but each process
> in the pool have it's own ThreadPoolExecutor inside.
>
> The motivation for this executor is mitigate the problem we have in a
> project were we have a very large number of long running IO bounded tasks,
> that have to run concurrently. Those long running tasks have sparse CPU
> bounded operations.
>
> To resolve this problem I considered multiple solutions:
>
>1. Use asyncio to run the IO part as tasks and use a
>ProcessPoolExecutor to run the CPU bounded operations with
>"run_in_executor". Unfortunately the CPU operations depends on a large
>memory context, and using a ProcessPoolExecutor this way force the parent
>process to picklelize all the context to send it to the task, and because
>the context is so large, this operation is itself very CPU demanding. So it
>doesn't work.
>2. Executing the IO/CPU bounded operations in different processes with
>multiprocessing.Process. This actually works, but the number of idle
>processes in the system is too large, resulting in a bad memory footprint.
>3. Executing the IO/CPU bounded operations in threads. This doesn't
>work because the sum of all CPU operations saturate the core where the
>Python process is running and the other cores are wasted doing nothing.
>
> So I coded the ThreadedProcessPoolExecutor that helped me maintaining the
> number of processes under control (I just have one process per CPU core)
> allowing me to have a very high concurrency (hundreds of threads per
> process).
>
> I have a couple of questions:
>
> The first one is about the license. Given that I copied the majority of
> the code from the concurrent.futures library, I understand that I have to
> publish the code under the PSF LICENSE. Is this correct?
>
> My second question is about the package namespace. Given that this is an
> concurrent.futures.Executor subclass I understand that more intuitive place
> to locate it is under concurrent.futures. Is this a suitable use case for
> namespace packages? Is this a good idea?
>
> Best regards,
> Roberto
>
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> guido%40python.org
>
>


-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Robert Smallshire
As requested on the bug tracker, I've submitted a pull request for
is_integer() support on the other numeric types.
https://github.com/python/cpython/pull/6121

These are the tactics I used to implement it:

- float: is_integer() already exists, so no changes

- int:  return True

- Real: return x == int(x). Although Real doesn't explicitly support
conversation to int with __int__, it does support conversion to int with
__trunc__. The int constructor falls back to using __trunc__.

- Rational (also inherited by Fraction): return x.denominator == 1 as
Rational requires that all numbers must be represented in lowest form.

- Integral: return True

- Decimal: expose the existing dec_mpd_isinteger C function to Python as
is_integer()
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Guido van Rossum
Thank you! As you may or may not have noticed in a different thread, we're
going through a small existential crisis regarding the usefulness of
is_integer() -- Serhiy believes it is not useful (and even an attractive
nuisance) and should be deprecated. OTOH the existence of
dec_mpd_isinteger() seems to validate to me that it actually exposes useful
functionality (and every Python feature can be abused, so that alone should
not be a strong argument for deprecation).

On Wed, Mar 21, 2018 at 1:33 AM, Robert Smallshire 
wrote:

> As requested on the bug tracker, I've submitted a pull request for
> is_integer() support on the other numeric types.
> https://github.com/python/cpython/pull/6121
>
> These are the tactics I used to implement it:
>
> - float: is_integer() already exists, so no changes
>
> - int:  return True
>
> - Real: return x == int(x). Although Real doesn't explicitly support
> conversation to int with __int__, it does support conversion to int with
> __trunc__. The int constructor falls back to using __trunc__.
>
> - Rational (also inherited by Fraction): return x.denominator == 1 as
> Rational requires that all numbers must be represented in lowest form.
>
> - Integral: return True
>
> - Decimal: expose the existing dec_mpd_isinteger C function to Python as
> is_integer()
>
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> guido%40python.org
>
>


-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] What is the purpose of NEXT_BLOCK()?

2018-03-21 Thread Serhiy Storchaka

21.03.18 17:13, Guido van Rossum пише:
Maybe spelunking in the Python 2 branch will help? It seems it was 
introduced in 2005 by Jeremy Hylton with this comment:


/* The distinction between NEW_BLOCK and NEXT_BLOCK is subtle.  (I'd
    like to find better names.)  NEW_BLOCK() creates a new block and sets
    it as the current block.  NEXT_BLOCK() also creates an implicit jump
    from the current block to the new block.
*/

That comment (and NEW_BLOCK()) are no longer found in the Python 3 source.


It explains what NEXT_BLOCK() does, but not why it was needed to do this.

NEW_BLOCK() was never used at all.

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Steve Holden
On Wed, Mar 21, 2018 at 3:08 PM, Guido van Rossum  wrote:

> I searched 6M LoC of Python code at Dropbox and found only three uses.
> They seem legit. Two are about formatting a number that's given as a float,
> deciding whether to print a float as 42 or 3.14. The third is attempting a
> conversion from float to integer where a non-integer must raise a specific
> exception (the same function also supports a string as long as it can be
> parsed as an int).
>
> I don't doubt we would get by if is_integer() was deprecated.
>
> ​Since code that's been deleted can't have bugs, +1.​
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Nathaniel Smith
On Mar 21, 2018 05:40, "Steven D'Aprano"  wrote:


I don't want to change the behaviour of pow(), but we shouldn't dismiss
the possibility of some other numeric function wanting to treat values
N.0 and N the same. Let's say, an is_prime(x) function that supports
floats as well as ints:

is_prime(3.0)  # True
is_prime(3.1)  # False


For me this is an argument against is_integer() rather than for it :-).
is_prime(float) should *obviously*[1] be a TypeError. Primality is only
meaningfully defined over the domain of integers, and this is a case where
operator.index is exactly what you want.

Of course it's just an example, and perhaps there are other, better
examples. But it makes me nervous that this is the best example you could
quickly come up with.

-n

[1] Warning: I am not Dutch.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Robert Smallshire
Here's an excerpted (and slightly simplified for consumption here) usage of
float.is_integer() from the top of a function which does some
convolution/filtering in a geophysics application. I've mostly seen it used
in guard clauses in this way to reject either illegal numeric arguments
directly, or particular combinations of arguments as in this case:

def filter_convolve(x, y, xf, yf, stride=1, padding=1):
x_out = (x - xf + 2*padding) / stride + 1
y_out = (y - yf + 2*padding) / stride + 1

if not (x_out.is_integer() and y_out.is_integer()):
raise ValueError("Invalid convolution filter_convolve({x},
{y}, {xf}, {yf}, {stride}, {padding})"
 .format(x=x, y=y, xf=xf, yf=yf,
stride=stride, padding=padding))
x_out = int(x_out)
y_out = int(y_out)

# ...

Of course, there are other ways to do this check, but the approach here is
obvious and easy to comprehend.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Mark Dickinson
I'd prefer to see `float.is_integer` stay. There _are_ occasions when one
wants to check that a floating-point number is integral, and on those
occasions, using `x.is_integer()` is the one obvious way to do it. I don't
think the fact that it can be misused should be grounds for deprecation.

As far as real uses: I didn't find uses of `is_integer` in our code base
here at Enthought, but I did find plenty of places where it _could_
reasonably have been used, and where something less readable like `x % 1 ==
0` was being used instead. For evidence that it's generally useful: it's
already been noted that the decimal module uses it internally. The mpmath
package defines its own "isint" function and uses it in several places: see
https://github.com/fredrik-johansson/mpmath/blob/2858b1000ffdd8596defb50381dcb83de2b6/mpmath/ctx_mp_python.py#L764.
MPFR also has an mpfr_integer_p predicate:
http://www.mpfr.org/mpfr-current/mpfr.html#index-mpfr_005finteger_005fp.

A concrete use-case: suppose you wanted to implement the beta function (
https://en.wikipedia.org/wiki/Beta_function) for real arguments in Python.
You'll likely need special handling for the poles, which occur only for
some negative integer arguments, so you'll need an is_integer test for
those. For small positive integer arguments, you may well want the accuracy
advantage that arises from computing the beta function in terms of
factorials (giving a correctly-rounded result) instead of via the log of
the gamma function. So again, you'll want an is_integer test to identify
those cases. (Oddly enough, I found myself looking at this recently as a
result of the thread about quartile definitions: there are links between
the beta function, the beta distribution, and order statistics, and the
(k-1/3)/(n+1/3) expression used in the recommended quartile definition
comes from an approximation to the median of a beta distribution with
integral parameters.)

Or, you could look at the SciPy implementation of the beta function, which
does indeed do the C equivalent of is_integer in many places:
https://github.com/scipy/scipy/blob/11509c4a98edded6c59423ac44ca1b7f28fba1fd/scipy/special/cephes/beta.c#L67

In sum: it's an occasionally useful operation; there's no other obvious,
readable spelling of the operation that does the right thing in all cases,
and it's _already_ in Python! In general, I'd think that deprecation of an
existing construct should not be done lightly, and should only be done when
there's an obvious and significant benefit to that deprecation. I don't see
that benefit here.

-- 
Mark
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] ThreadedProcessPoolExecutor

2018-03-21 Thread Roberto Martínez
El mié., 21 mar. 2018 a las 16:23, Guido van Rossum ()
escribió:

> Roberto,
>
> That looks like an interesting class. I presume you're intending to
> publish this as a pip package on PyPI.python.org?
>
>
Precisely.

I'm no lawyer, but I believe you can license your code under a new license
> (I recommend BSD) as long as you keep a copy and a mention of the PSF
> license in your distribution as well. (Though perhaps you could structure
> your code differently and inherit from the standard library modules rather
> than copying them?)
>

I am using inheritance as much as I can. But due to some functions being at
the module level, instead of being Executor methods (for the sake of being
pickelizable, I suppose); I am being forced to copy some of them just to
modify a couple of lines.


> In terms of the package namespace, do not put it in the same namespace as
> standard library code! It probably won't work and will cause world-wide
> pain and suffering for the users of your code. Invent your project name and
> use that as a top-level namespace, like everyone else. :-)
>
>
Ok, I don't want to cause world-wide pain (yet).

Thank you!

Best regards,
Roberto

>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread David Mertz
I've been using and teaching python for close to 20 years and I never
noticed that x.is_integer() exists until this thread. I would say the "one
obvious way" is less than obvious.

On the other hand, `x == int(x)` is genuinely obvious... and it immediately
suggests the probably better `math.isclose(x, int(x))` that is what you
usually mean.

On Wed, Mar 21, 2018, 2:08 PM Mark Dickinson  wrote:

> I'd prefer to see `float.is_integer` stay. There _are_ occasions when one
> wants to check that a floating-point number is integral, and on those
> occasions, using `x.is_integer()` is the one obvious way to do it. I don't
> think the fact that it can be misused should be grounds for deprecation.
>
> As far as real uses: I didn't find uses of `is_integer` in our code base
> here at Enthought, but I did find plenty of places where it _could_
> reasonably have been used, and where something less readable like `x % 1 ==
> 0` was being used instead. For evidence that it's generally useful: it's
> already been noted that the decimal module uses it internally. The mpmath
> package defines its own "isint" function and uses it in several places: see
> https://github.com/fredrik-johansson/mpmath/blob/2858b1000ffdd8596defb50381dcb83de2b6/mpmath/ctx_mp_python.py#L764.
> MPFR also has an mpfr_integer_p predicate:
> http://www.mpfr.org/mpfr-current/mpfr.html#index-mpfr_005finteger_005fp.
>
> A concrete use-case: suppose you wanted to implement the beta function (
> https://en.wikipedia.org/wiki/Beta_function) for real arguments in
> Python. You'll likely need special handling for the poles, which occur only
> for some negative integer arguments, so you'll need an is_integer test for
> those. For small positive integer arguments, you may well want the accuracy
> advantage that arises from computing the beta function in terms of
> factorials (giving a correctly-rounded result) instead of via the log of
> the gamma function. So again, you'll want an is_integer test to identify
> those cases. (Oddly enough, I found myself looking at this recently as a
> result of the thread about quartile definitions: there are links between
> the beta function, the beta distribution, and order statistics, and the
> (k-1/3)/(n+1/3) expression used in the recommended quartile definition
> comes from an approximation to the median of a beta distribution with
> integral parameters.)
>
> Or, you could look at the SciPy implementation of the beta function, which
> does indeed do the C equivalent of is_integer in many places:
> https://github.com/scipy/scipy/blob/11509c4a98edded6c59423ac44ca1b7f28fba1fd/scipy/special/cephes/beta.c#L67
>
> In sum: it's an occasionally useful operation; there's no other obvious,
> readable spelling of the operation that does the right thing in all cases,
> and it's _already_ in Python! In general, I'd think that deprecation of an
> existing construct should not be done lightly, and should only be done when
> there's an obvious and significant benefit to that deprecation. I don't see
> that benefit here.
>
> --
> Mark
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/mertz%40gnosis.cx
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Guido van Rossum
On Wed, Mar 21, 2018 at 11:14 AM, David Mertz  wrote:

> I've been using and teaching python for close to 20 years and I never
> noticed that x.is_integer() exists until this thread. I would say the "one
> obvious way" is less than obvious.
>
> On the other hand, `x == int(x)` is genuinely obvious... and it
> immediately suggests the probably better `math.isclose(x, int(x))` that is
> what you usually mean.
>

We can argue about this forever, but I don't think I would have come up
with that either when asked "how to test a float for being a whole number".
I would probably have tried "x%1 == 0" which is terrible. I like to have an
API that doesn't have the pitfalls of any of the "obvious" solutions that
numerically naive people would come up with, and x.is_integer() is it.
Let's keep it.

-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Tim Peters
[David Mertz]
> I've been using and teaching python for close to 20 years and I never
> noticed that x.is_integer() exists until this thread.

Except it was impossible to notice across most of those years, because
it didn't exist across most of those years ;-)


> I would say the "one obvious way" is less than obvious.

When it was introduced, it _became_ the one obvious way.


> On the other hand, `x == int(x)` is genuinely obvious..

But a bad approach:  it can raise OverflowError (for infinite x); it
can raise ValueError (for x a NaN); and can waste relative mountains
of time creating huge integers, e.g.,

>>> int(1e306)
117216064596736454828831087825013238982328892017892380671244575047987920451875459594568606138861698291060311049225532948520696938805711440650122628514669428460356992624968028329550689224175284346730060716088829214255439694630119794546505512415617982143262670862918816362862119154749127262208

In Python 2, x == math.floor(x) was much better on the latter count,
but not in Python 3 (math.floor used to return a float, but returns an
int now).


As to Serhiy's `not x % 1.0`, after 5 minutes I gave up trying to
prove it's always correct.  Besides infinities and NaNs, there's also
that Python's float mod can be surprising:

>>> (-1e-20) % 1.0
1.0

There isn't a "clean" mathematical definition of what Python's float %
does, which is why proof is strained.  In general, the "natural"
result is patched when and if needed to maintain that

x == y*(x//y) + x%y

is approximately true.  The odd % result above is a consequence of
that, and that (-1e-20) // 1.0 is inarguably -1.0.


> and it immediately suggests the probably better `math.isclose(x, int(x))` that
> is what you usually mean.

Even in some of the poor cases Serhiy found, that wouldn't be a lick
better.  For example,

math.isclose(x/5, int(x/5))

is still a plain wrong way to check whether x is divisible by 5.

>>> x = 1e306
>>> math.isclose(x/5, int(x/5))
True
>>> x/5 == int(x/5)
True
>>> int(x) % 5
3

The problem there isn't  how "is it an integer?" is spelled, it's that
_any_ way of spelling "is it an integer?" doesn't answer the question
they're trying to answer.  They're just plain confused about how
floating point works.  The use of `.is_integer()` (however spelled!)
isn't the cause of that, it's a symptom.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread David Mertz
On Wed, Mar 21, 2018 at 3:02 PM, Tim Peters  wrote:

> [David Mertz]
> > I've been using and teaching python for close to 20 years and I never
> > noticed that x.is_integer() exists until this thread.
>
> Except it was impossible to notice across most of those years, because
> it didn't exist across most of those years ;-)
>

That's probably some of the reason.  I wasn't sure if someone used the time
machine to stick it back into Python 1.4.


> > On the other hand, `x == int(x)` is genuinely obvious..
>
> But a bad approach:  it can raise OverflowError (for infinite x); it
> can raise ValueError (for x a NaN);


These are the CORRECT answers! Infinity neither is nor is not an integer.
Returning a boolean as an answer is bad behavior; I might argue about
*which* exception is best, but False is not a good answer to
`float('inf').is_integer()`.  Infinity is neither in the Reals nor in the
Integers, but it's just as much the limit of either.

Likewise Not-a-Number isn't any less an integer than it is a real number
(approximated by a floating point number).  It's NOT a number, which is
just as much not an integer.


> and can waste relative mountains
> of time creating huge integers, e.g.,
>

True enough. But it's hard to see where that should matter.  No floating
point number on the order of 1e306 is sufficiently precise as to be an
integer in any meaningful sense.  If you are doing number theory with
integers of that size (or larger is perfectly fine too) the actual test is
`isinstance(x, int)`.  Using a float is just simply wrong for the task to
start with, whether or not those bits happen to represent something
Integral... the only case where you should see this is
"measuring/estimating something VERY big, very approximately."

For example, this can be true (even without reaching inf):

>>> x.is_integer()
True
>>> (math.sqrt(x**2)).is_integer()
False

The problem there isn't  how "is it an integer?" is spelled, it's that
> _any_ way of spelling "is it an integer?" doesn't answer the question
> they're trying to answer.  They're just plain confused about how
> floating point works.  The use of `.is_integer()` (however spelled!)
> isn't the cause of that, it's a symptom.
>

Agreed!

-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Mark Dickinson
On Wed, Mar 21, 2018 at 8:49 PM, David Mertz  wrote:

> For example, this can be true (even without reaching inf):
>
> >>> x.is_integer()
> True
> >>> (math.sqrt(x**2)).is_integer()
> False
>

If you have a moment to share it, I'd be interested to know what value of
`x` you used to achieve this, and what system you were on. This can't
happen under IEEE 754 arithmetic.

-- 
Mark
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Steven D'Aprano
On Wed, Mar 21, 2018 at 09:46:06AM -0700, Nathaniel Smith wrote:
[...]
> For me this is an argument against is_integer() rather than for it :-).
> is_prime(float) should *obviously*[1] be a TypeError. Primality is only
> meaningfully defined over the domain of integers

And 3.0 is an integer. Just because it is float *object* does not mean 
it is not an integer *value*. Do not mistake the leaky abstraction of 
multiple numeric types for the mathematical number three.

Primality-related functions are not limited to integers. For example, 
the prime counting function is defined on the reals:

https://en.wikipedia.org/wiki/Prime-counting_function

and there's no reason not to extend the domain of is_prime to any real. 
"Practicality beats purity" -- why should the result be different just 
because the input has a ".0" at the end?

Mathematically it doesn't: the answer to something like "Is 3.0 a 
prime?" is a clear Yes, not "I'm sorry, I don't understand the 
question!" which an exception would imply.

As programmers, there is always a tension between the leaky abstraction 
of our numeric types, and the mathematical equality of:

3 == 3.0 == 9/3 == 3+0j

etc. The decision on whether to be more or less restrictive on the 
*types* a function accepts is up to the individual developer. Having 
decided to be *less* restrictive, an is_integer method would be useful.

For what it's worth, Wolfram|Alpha gives inconsistant results. It allows 
testing of rationals for primality:

"Is 9/3 a prime?"

evaluates as true, but:

"Is 3.0 a prime?"

gets parsed as "Is 3 a prime number?" and yet evaluates as false. A 
clear bug for software using a natural-language interface and intended 
to be used by students and non-mathematicans.


> and this is a case where
> operator.index is exactly what you want.

It is exactly not what I want. 


> Of course it's just an example, and perhaps there are other, better
> examples. But it makes me nervous that this is the best example you could
> quickly come up with.

I actually had to work hard to come up with an example as simple and 
understandable as primality testing. The first example I thought of was 
Bessel functions of the 1st and 2nd kind with arbitrary real-valued 
orders, where you *absolutely* do want order 3.0 (float) and order 3 
(int) to be precisely the same.

But I avoided giving it because I thought it would be too technical and 
it would intimidate people. I thought that the prime number example 
would be easier to understand.

Next time I want to make a point, I'll go for argument by intimidation.

*wink*


-- 
Steve

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Tim Peters
Note:  this is a top-posted essay much more about floating-point
philosophy than about details.  Details follow from the philosophy,
and if philosophies don't match the desired details will never match
either.

Understanding floating point requires accepting that they're a funky
subset of rational numbers, augmented with some oddballs (NaNs,
"infinities", minus zero).  At best the reals are a vague inspiration,
and floats have their own terminology serving their actual nature.
Thinking about reals instead is often unhelpful.

For example, it's bog standard terminology to call all IEEE-754 values
that aren't infinities or NaNs "finite".  Which, by no coincidence, is
how Python's math.isfinite() discriminates.  Within the finites -
which are all rational numbers - the distinction between integers and
non-integers is obvious, but only after you're aware of it and give it
some thought.  Which most people aren't and don't - but that's no
reason to prevent the rest of us from getting work done ;-)

This isn't anything new in Python - it's as old as floating-point.
For example, look up C's ancient "modf" function (which breaks a
float/double into its "integer" and "fractional" parts, and treats all
finite floats of sufficiently large magnitude as having fractional
parts of 0.0 - because they in are fact exact integers).

The idea that floats are "just approximations - so all kinds of slop
is acceptable and all kinds of fear inescapable" went out of style
when IEEE-754 was introduced.  That standard codified an alternative
view:  that functions on floats should behave as if their inputs were
_exactly_ correct, and - given that - produce the closest
representable value to the infinitely precise result.  That proved to
be extremely valuable in practice, allowing the development of
shorter, faster, more robust, and more accurate numerical algorithms.

The trend ever since has been to do more & more along those lines,
from trig functions doing argument reduction as if pi were represented
with infinite precision, to adding single-rounding dot product
primitives (all again acting as if all the inputs were exactly
correct).

Since that approach has been highly productive in real life, it's the
one I favor.  Arguments like "no floating point number on the order of
1e306 is sufficiently precise as to be an integer in any meaningful
sense" don't even start to get off the ground in that approach.  Maybe
in 1970 ;-)  You can have no actual idea of whether 1e306 is exactly
right or off by a factor of a million just from staring at it, and
real progress has been made by assuming all values are exactly what
they appear to be, then acting accordingly.  If you want to model that
some values are uncertain, that's fine, but then you need something
like interval arithmetic instead.

>From that fundamental "take floats exactly at face value" view, what
.is_integer() should do for floats is utterly obvious:  there is no
possible argument about whether a given IEEE-754 float is or is not an
integer, provided you're thinking about IEEE-754 floats (and not,
e.g., about mathematical reals), and making even a tiny attempt to
honor the spirit of the IEEE-754 standard.

Whether that's _useful_ to you depends on the application you're
writing at the time.  The advantage of the philosophy is that it often
gives clear guidance about what implementations "should do"
regardless, and following that guidance has repeatedly proved to be a
boon to those writing numerical methods.  And, yes, also a pain in the
ass ;-)

--- nothing new below ---

On Wed, Mar 21, 2018 at 3:49 PM, David Mertz  wrote:
> On Wed, Mar 21, 2018 at 3:02 PM, Tim Peters  wrote:
>>
>> [David Mertz]
>> > I've been using and teaching python for close to 20 years and I never
>> > noticed that x.is_integer() exists until this thread.
>>
>> Except it was impossible to notice across most of those years, because
>> it didn't exist across most of those years ;-)
>
>
> That's probably some of the reason.  I wasn't sure if someone used the time
> machine to stick it back into Python 1.4.
>
>>
>> > On the other hand, `x == int(x)` is genuinely obvious..
>>
>> But a bad approach:  it can raise OverflowError (for infinite x); it
>> can raise ValueError (for x a NaN);
>
>
> These are the CORRECT answers! Infinity neither is nor is not an integer.
> Returning a boolean as an answer is bad behavior; I might argue about
> *which* exception is best, but False is not a good answer to
> `float('inf').is_integer()`.  Infinity is neither in the Reals nor in the
> Integers, but it's just as much the limit of either.
>
> Likewise Not-a-Number isn't any less an integer than it is a real number
> (approximated by a floating point number).  It's NOT a number, which is just
> as much not an integer.
>
>>
>> and can waste relative mountains
>> of time creating huge integers, e.g.,
>
>
> True enough. But it's hard to see where that should matter.  No floating
> point number on the order of 1e306 is sufficientl

Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Tim Peters
[David Mertz ]
>> For example, this can be true (even without reaching inf):
>>
>> >>> x.is_integer()
>> True
>> >>> (math.sqrt(x**2)).is_integer()
>> False

[Mark Dickinson  ]
> If you have a moment to share it, I'd be interested to know what value of
> `x` you used to achieve this, and what system you were on. This can't happen
> under IEEE 754 arithmetic.

I expect it might happen under one of the directed rounding modes
(like "to +infinity").

But under 754 binary round-nearest/even arithmetic, it's been formally
proved that sqrt(x*x) == x exactly for all non-negative finite x such
that x*x neither overflows nor underflows (and .as_integer() has
nothing to do with that very strong result):

https://hal.inria.fr/hal-01148409/document

OTOH, the paper notes that it's not necessarily true for IEEE decimal
arithmetic; e.g.,

>>> import decimal
>>> decimal.getcontext().prec = 4
>>> (decimal.Decimal("31.66") ** 2).sqrt()  # result is 1 ulp smaller
Decimal('31.65')

>>> decimal.getcontext().prec = 5
>>> (decimal.Decimal("31.660") ** 2).sqrt() # result is 1 ulp larger
Decimal('31.661')
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Devin Jeanpierre
> [Mark Dickinson  ]
>> If you have a moment to share it, I'd be interested to know what value of
>> `x` you used to achieve this, and what system you were on. This can't happen
>> under IEEE 754 arithmetic.
>
> I expect it might happen under one of the directed rounding modes
> (like "to +infinity").

PyPy (5.8):

 x = 1e300
 x.is_integer()
True
 math.sqrt(x**2).is_integer()
False
 x**2
inf

(It gives an OverflowError on my CPython installs.)

I believe this is allowed, and Python is not required to raise
OverflowError here:
https://docs.python.org/3.6/library/exceptions.html#OverflowError
says:

> for historical reasons, OverflowError is sometimes raised for integers that 
> are outside a required range. Because of the lack of standardization of 
> floating point exception handling in C, most floating point operations are 
> not checked

-- Devin
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Chris Barker
On Wed, Mar 21, 2018 at 11:43 PM, Tim Peters  wrote:

> Note:  this is a top-posted essay much more about floating-point
> philosophy than about details.  Details follow from the philosophy,
> and if philosophies don't match the desired details will never match
> either.
>

but of course :-)


> From that fundamental "take floats exactly at face value" view, what
> .is_integer() should do for floats is utterly obvious:


sure -- but I don't think anyone is arguing that -- the question is whether
the function should exist -- and that means not "how should it work?" or
"is it clearly and appropriately defined?" but rather, "is it the "right"
thing to do in most cases, when deployed by folks that haven't thought
deeply about floating point.

> Whether that's _useful_ to you depends on the application you're

> writing at the time.


exactly.

I think pretty much all the real world code that's been shown here for
using .is_integer() is really about type errors (issues). The function at
hand really wants integer inputs -- but wants to allow the user to be
sloppy and provide a float type that happens to be an int. Given Python's
duck-typing nature, maybe that's a good thing? I know I really discourage
dynamic type checking

Also, every example has been for small-ish integers -- exponents,
factorials, etc -- not order 1e300 -- or inf or NaN, etc.

Finally, the use-cases where the value that happens-to-be-an-int is
computed via floating point -- .is_integer() is probably the wrong check --
you probably want  isclose().

The other use-cases: and floor() and ceil() and round() all produce actual
integers -- so no need for that anymore.

All this points to: we don't need .is_integer

All the being said -- the standard for depreciation is much higher bar than
not-adding-it-in-the-first-place.

-CHB


-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Tim Peters
[Devin Jeanpierre ]
> PyPy (5.8):
>  x = 1e300
>  x.is_integer()
> True
>  math.sqrt(x**2).is_integer()
> False
>  x**2
> inf

I think you missed that David said "even without reaching inf" (you
did reach inf), and that I said "such that x*x neither overflows nor
underflows".  Those are technical words related to IEEE-754:  your x*x
sets the IEEE overflow flag, although CPython may or may not raise the
Python OverflowError exception.

>
> (It gives an OverflowError on my CPython installs.)
>
> I believe this is allowed, and Python is not required to raise
> OverflowError here:
> https://docs.python.org/3.6/library/exceptions.html#OverflowError
> says:
>
>> for historical reasons, OverflowError is sometimes raised for integers that 
>> are outside a required range. Because of the lack of standardization of 
>> floating point exception handling in C, most floating point operations are 
>> not checked

You can avoid the OverflowError (but not the IEEE overflow condition!)
under CPython by multiplying instead:

>>> x = 1e300
>>> x*x
inf
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Chris Barker
On Wed, Mar 21, 2018 at 12:38 PM, Steven D'Aprano 
wrote:

> In fact, Serhiy's suggestion is not correct when x is not a float:
>

This is a key point -- see some of Tim's posts -- like ot or not, you
probably need to know when you are working with a float and when you aren't
-- and what the implications of that are.

I think the key pint is this:

where does the logic of whether a given object represents an integer
belong? At first glance, it clearly belongs with the type -- floats know
how they are represented, as do fractions and decimals -- they can
determine it in an efficient and clearly defined way.

However, my argument is that while an integer-valued float is clearly
defined in the binary representation, what "is this an integer?" means is
actually use-case dependent, and thus the user should be deciding how to do
it (i.e. with isclose() or int(x) == x or 

> If the exponent is a computed float, then you

> > really don’t want a different result depending on whether the computed
> > value is exactly an integer or one ULP off.
>
> I don't think you actually mean to say that. I'm pretty sure that we
> *do* want different results if the exponent differs from an integer by
> one ULP.


yes -- poorly worded -- I mean you want the slightly different result, not
a different type and algorithm - i.e continuity if you had a range of
slightly less than an integer to slightly more than an integer.

> The user should check/convert to an integer with a method appropriate to

> > the problem at hand.
>
> Oh, you mean something like x.is_integer()? I agree!
>
> *wink*
>

That's the point -- is_integer may or may not be appropriate, and whether
it is is a function of use-case, not type.

> If it wasn’t too heavyweight, it might be nice to have some sort of flag
> on
> > floats indicating whether they really ARE an integer, rather than happen
> to
> > be:
> >
> > -Created from an integer literal
> > - created from an integer object
> > - result of floor(), ceil() or round()
>
> I don't understand this.
>

poorly worked again -- I shoud not write these on a phone


> You seem to be saying that none of the following are "really" integer
> valued:
>
> float(10)
> floor(10.1)
> ceil(10.1)
> round(10.1)
>

I meant those are the ones that ARE really integer valued.

turns out that py3 returns an actual int for all of those other than
float() (of course) anyway, so that's pretty much been done -- and no need
for is_integer()

well, it's been fun, but looks like it's sticking around.


-CHB



-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Chris Barker
On Wed, Mar 21, 2018 at 4:12 PM, Guido van Rossum  wrote:

> Thank you! As you may or may not have noticed in a different thread, we're
> going through a small existential crisis regarding the usefulness of
> is_integer() -- Serhiy believes it is not useful (and even an attractive
> nuisance) and should be deprecated. OTOH the existence of
> dec_mpd_isinteger() seems to validate to me that it actually exposes useful
> functionality (and every Python feature can be abused, so that alone should
> not be a strong argument for deprecation).
>

if not deprecated, then do we add it to all the other numeric types? Which
was the original suggestion, yes?

-CHB




-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread David Mertz
Ok. I'm wrong on that example.

On Wed, Mar 21, 2018, 9:11 PM Tim Peters  wrote:

> [David Mertz ]
> >> For example, this can be true (even without reaching inf):
> >>
> >> >>> x.is_integer()
> >> True
> >> >>> (math.sqrt(x**2)).is_integer()
> >> False
>
> [Mark Dickinson  ]
> > If you have a moment to share it, I'd be interested to know what value of
> > `x` you used to achieve this, and what system you were on. This can't
> happen
> > under IEEE 754 arithmetic.
>
> I expect it might happen under one of the directed rounding modes
> (like "to +infinity").
>
> But under 754 binary round-nearest/even arithmetic, it's been formally
> proved that sqrt(x*x) == x exactly for all non-negative finite x such
> that x*x neither overflows nor underflows (and .as_integer() has
> nothing to do with that very strong result):
>
> https://hal.inria.fr/hal-01148409/document
>
> OTOH, the paper notes that it's not necessarily true for IEEE decimal
> arithmetic; e.g.,
>
> >>> import decimal
> >>> decimal.getcontext().prec = 4
> >>> (decimal.Decimal("31.66") ** 2).sqrt()  # result is 1 ulp smaller
> Decimal('31.65')
>
> >>> decimal.getcontext().prec = 5
> >>> (decimal.Decimal("31.660") ** 2).sqrt() # result is 1 ulp larger
> Decimal('31.661')
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Tim Peters
[Chris Barker ]
> ...
> ... "is it the "right" thing to do in most cases, when deployed by folks
> that haven't thought deeply about floating point.

Gimme a break ;-)  Even people who _believe_ they've thought about
floating point still litter the bug tracker with

>>> .1 + .2
0.30004

"bug reports".  .is_integer() is easy to explain compared to that  -
and you have to go out of your way to use it.

> ...
> I think pretty much all the real world code that's been shown here for using
> .is_integer() is really about type errors (issues). The function at hand
> really wants integer inputs -- but wants to allow the user to be sloppy and
> provide a float type that happens to be an int. Given Python's duck-typing
> nature, maybe that's a good thing? I know I really discourage dynamic type
> checking

So you identified a use case.  One you don't approve of (nor do I),
but not strongly enough to demand they suffer instead ;-)


> Also, every example has been for small-ish integers -- exponents,
> factorials, etc -- not order 1e300 -- or inf or NaN, etc.
>
> Finally, the use-cases where the value that happens-to-be-an-int is computed
> via floating point -- .is_integer() is probably the wrong check -- you
> probably want  isclose().

Everyone who has implemented a production math library can recall
cases where the functionality was needed.  Here, that includes at
least Stefan Krah and me.  You could also follow the link from Mark
Dickinson to SciPy's implementation of the beta function.

In every case I've needed the functionality, isclose() would have been
utterly useless.  Behold:

>>> (-1.0) ** 3.0
-1.0
>>> (-1.0) ** 3.0001  # different result _type_
(-1-3.142007854859299e-12j)
>>> math.isclose(3.0, 3.0001)
True

And another showing that the same functionality is needed regardless
of how large the power:

>>> (-1.0) ** 1e300  # an even integer power
1.0

When implementing an externally defined standard, when it says "and if
such-and-such is an integer ...", it _means_ exactly an integer, not
"or a few ULP away from an integer".  IEEE pow()-like functions
bristle with special cases for integers.

>>> (-math.inf) ** 3.1
inf
>>> (-math.inf) ** 3.0 # note: this one has a negative result (odd integer 
>>> power)
-inf
>>> (-math.inf) ** 2.9
inf


> ...
> All this points to: we don't need .is_integer

I'll grant that you don't think you need it.  So don't use it ;-)


> All the being said -- the standard for depreciation is much higher bar than
> not-adding-it-in-the-first-place.

I would not have added it as a method to begin with - but I agree with
Guido that it doesn't reach the bar for deprecation.  The only
examples of "bad" uses we saw were from people still so naive about
floating-point behavior that they'll easily fall into other ways to
get it wrong.  What we haven't seen:  a single person here saying "you
know, I think _I'd_ be seduced into misusing it!".  It's not
_inherently_ confusing at all.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Symmetry arguments for API expansion

2018-03-21 Thread Guido van Rossum
On Wed, Mar 21, 2018 at 6:48 PM, Chris Barker  wrote:

> On Wed, Mar 21, 2018 at 4:12 PM, Guido van Rossum 
> wrote:
>
>> Thank you! As you may or may not have noticed in a different thread,
>> we're going through a small existential crisis regarding the usefulness of
>> is_integer() -- Serhiy believes it is not useful (and even an attractive
>> nuisance) and should be deprecated. OTOH the existence of
>> dec_mpd_isinteger() seems to validate to me that it actually exposes useful
>> functionality (and every Python feature can be abused, so that alone should
>> not be a strong argument for deprecation).
>>
>
> if not deprecated, then do we add it to all the other numeric types? Which
> was the original suggestion, yes?
>

Yes. That's a pronouncement, so we can end this thread (and more
importantly the other).

-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Guido van Rossum
OK, we'll keep float.is_integer(), and that's a pronouncement, so that we
can hopefully end this thread soon.

It should also be added to int. After all that's what started this thread,
with the observation that mypy and PEP 484 consider an int valid whenever a
float is expected.

Since PEP 484 and mypy frown upon the numeric tower I don't care too much
about whether it's added it there (or to Decimal) but given that we're
keeping float.is_integer() and adding int.is_integer(), I don't see what's
gained by not adding it to the numeric tower and Decimal either.

Numpy can do what it likes, it doesn't play by the same rules as the stdlib
anyway.

On Wed, Mar 21, 2018 at 7:29 PM, Tim Peters  wrote:

> [Chris Barker ]
> > ...
> > ... "is it the "right" thing to do in most cases, when deployed by folks
> > that haven't thought deeply about floating point.
>
> Gimme a break ;-)  Even people who _believe_ they've thought about
> floating point still litter the bug tracker with
>
> >>> .1 + .2
> 0.30004
>
> "bug reports".  .is_integer() is easy to explain compared to that  -
> and you have to go out of your way to use it.
>
> > ...
> > I think pretty much all the real world code that's been shown here for
> using
> > .is_integer() is really about type errors (issues). The function at hand
> > really wants integer inputs -- but wants to allow the user to be sloppy
> and
> > provide a float type that happens to be an int. Given Python's
> duck-typing
> > nature, maybe that's a good thing? I know I really discourage dynamic
> type
> > checking
>
> So you identified a use case.  One you don't approve of (nor do I),
> but not strongly enough to demand they suffer instead ;-)
>
>
> > Also, every example has been for small-ish integers -- exponents,
> > factorials, etc -- not order 1e300 -- or inf or NaN, etc.
> >
> > Finally, the use-cases where the value that happens-to-be-an-int is
> computed
> > via floating point -- .is_integer() is probably the wrong check -- you
> > probably want  isclose().
>
> Everyone who has implemented a production math library can recall
> cases where the functionality was needed.  Here, that includes at
> least Stefan Krah and me.  You could also follow the link from Mark
> Dickinson to SciPy's implementation of the beta function.
>
> In every case I've needed the functionality, isclose() would have been
> utterly useless.  Behold:
>
> >>> (-1.0) ** 3.0
> -1.0
> >>> (-1.0) ** 3.0001  # different result _type_
> (-1-3.142007854859299e-12j)
> >>> math.isclose(3.0, 3.0001)
> True
>
> And another showing that the same functionality is needed regardless
> of how large the power:
>
> >>> (-1.0) ** 1e300  # an even integer power
> 1.0
>
> When implementing an externally defined standard, when it says "and if
> such-and-such is an integer ...", it _means_ exactly an integer, not
> "or a few ULP away from an integer".  IEEE pow()-like functions
> bristle with special cases for integers.
>
> >>> (-math.inf) ** 3.1
> inf
> >>> (-math.inf) ** 3.0 # note: this one has a negative result (odd integer
> power)
> -inf
> >>> (-math.inf) ** 2.9
> inf
>
>
> > ...
> > All this points to: we don't need .is_integer
>
> I'll grant that you don't think you need it.  So don't use it ;-)
>
>
> > All the being said -- the standard for depreciation is much higher bar
> than
> > not-adding-it-in-the-first-place.
>
> I would not have added it as a method to begin with - but I agree with
> Guido that it doesn't reach the bar for deprecation.  The only
> examples of "bad" uses we saw were from people still so naive about
> floating-point behavior that they'll easily fall into other ways to
> get it wrong.  What we haven't seen:  a single person here saying "you
> know, I think _I'd_ be seduced into misusing it!".  It's not
> _inherently_ confusing at all.
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> guido%40python.org
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Greg Ewing

Tim Peters wrote:

from trig functions doing argument reduction as if pi were represented
with infinite precision,


That sounds like an interesting trick! Can you provide
pointers to any literature describing how it's done?

Not doubting it's possible, just curious.

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Deprecating float.is_integer()

2018-03-21 Thread Tim Peters
[Tim]
>> from trig functions doing argument reduction as if pi were represented
>> with infinite precision,

[Greg Ewing ]
> That sounds like an interesting trick! Can you provide
> pointers to any literature describing how it's done?
>
> Not doubting it's possible, just curious.

As I recall, when it was first done a "lazy" routine produced as many
bits of pi as a given argument required, doing gonzo arbitrary
precision arithmetic.

Later, computer-aided analysis based on continued fraction expansions
identified the worst possible case across all IEEE doubles (&
singles).  For example, it's possible in reasonable time to find the
IEEE double that comes closest to being an exact integer multiple of
pi/4 (or whatever other range you want to reduce to).  Then it's only
necessary to precompute pi to as many bits as needed to handle the
worst case.

In practice, falling back to that is necessary only for "large"
arguments, and the usual double-precision numeric tricks suffice for
smaller arguments.

Search the web for "trig argument reduction" for whatever the state of
the art may be today ;-)

For actual code, FDLIBM does "as if infinite precision" trig argument
reduction, using a precomputed number of pi bits sufficient to handle
the worst possible IEEE double case, and is available for free from
NETLIB:

http://www.netlib.org/fdlibm/

The code is likely to be baffling, though, as there's scant
explanation.  Reading a paper or two first would be a huge help.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Do we have vlookup function

2018-03-21 Thread Rohit Adhikari
Do we have vlookup function which can be used in dataframe same as used in
excel.
Can you please provide the pointer for the same?

Thanks!!!
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com