Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bizarre arithmetic results

2 views
Skip to first unread message

Terrence Cole

unread,
Feb 10, 2010, 7:44:13 PM2/10/10
to pytho...@python.org
Can someone explain to me what python is doing here?

Python 3.1.1 (r311:74480, Feb 3 2010, 13:36:47)
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> -0.1 ** 0.1
-0.7943282347242815
>>> a = -0.1; b = 0.1
>>> a ** b
(0.7554510437117542+0.2454609236416552j)
>>> -abs(a ** b)
-0.7943282347242815

Why does the literal version return the signed magnitude and the
variable version return a complex?

Cheers,
Terrence

Mark Dickinson

unread,
Feb 11, 2010, 7:27:14 AM2/11/10
to
On Feb 11, 12:44 am, Terrence Cole <list-

s...@trainedmonkeystudios.org> wrote:
> Can someone explain to me what python is doing here?

> >>> -0.1 ** 0.1
> -0.7943282347242815

Here you're computing -(0.1 ** 0.1). The exponentiation operator
binds more strongly than the negation operator.

> >>> a = -0.1; b = 0.1
> >>> a ** b
> (0.7554510437117542+0.2454609236416552j)

Here you're computing (-0.1) ** 0.1.

--
Mark

Andre Engels

unread,
Feb 11, 2010, 7:26:56 AM2/11/10
to terr...@zettabytestorage.com, pytho...@python.org
On Thu, Feb 11, 2010 at 1:44 AM, Terrence Cole
<list...@trainedmonkeystudios.org> wrote:
> Can someone explain to me what python is doing here?
>
> Python 3.1.1 (r311:74480, Feb  3 2010, 13:36:47)
> [GCC 4.3.4] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> -0.1 ** 0.1
> -0.7943282347242815
>>>> a = -0.1; b = 0.1
>>>> a ** b
> (0.7554510437117542+0.2454609236416552j)
>>>> -abs(a ** b)
> -0.7943282347242815
>
> Why does the literal version return the signed magnitude and the
> variable version return a complex?

It's an issue of precedence of operators:

-0.1 ** 0.1

is interpreted as

-(0.1 ** 0.1)

and not as

(-0.1) ** 0.1


--
André Engels, andre...@gmail.com

Peter Otten

unread,
Feb 11, 2010, 7:25:47 AM2/11/10
to
Terrence Cole wrote:

Operator precedence.

>>> -0.1**0.1
-0.7943282347242815
>>> (-0.1)**0.1
(0.7554510437117542+0.2454609236416552j)

Quoting http://docs.python.org/3.1/reference/expressions.html:

"""
The power operator binds more tightly than unary operators on its left; it
binds less tightly than unary operators on its right.
"""

Peter

Christian Heimes

unread,
Feb 11, 2010, 7:33:37 AM2/11/10
to pytho...@python.org
Terrence Cole wrote:
>>>> -0.1 ** 0.1
> -0.7943282347242815
>>>> a = -0.1; b = 0.1
>>>> a ** b
> (0.7554510437117542+0.2454609236416552j)
>>>> -abs(a ** b)
> -0.7943282347242815
>
> Why does the literal version return the signed magnitude and the
> variable version return a complex?

The binary power operator has a higher precedence than the unary
negative operator. -0.1 ** 0.1 is equal to -(0.1**0.1)

Christian

Jussi Piitulainen

unread,
Feb 11, 2010, 7:37:45 AM2/11/10
to
Terrence Cole writes:

The minus sign is not part of the literal syntax. Python takes the
expression as -(0.1 ** 0.1), the binary operator binding tighter than
the unary.

Try (-0.1) ** 0.1, and try a = 0.1, then -a ** 0.1.

Tim Chase

unread,
Feb 11, 2010, 7:47:56 AM2/11/10
to terr...@zettabytestorage.com, pytho...@python.org
Terrence Cole wrote:
> Can someone explain to me what python is doing here?
>
> Python 3.1.1 (r311:74480, Feb 3 2010, 13:36:47)
> [GCC 4.3.4] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> -0.1 ** 0.1
> -0.7943282347242815
>>>> a = -0.1; b = 0.1
>>>> a ** b
> (0.7554510437117542+0.2454609236416552j)
>>>> -abs(a ** b)
> -0.7943282347242815
>
> Why does the literal version return the signed magnitude and the
> variable version return a complex?

I think this recently showed up on the list and the answer
involved the order of operations and precedence of "-" vs. "**".
To check, try

>>> (-0.1) ** 0.1
>>> -(0.1 ** 0.1)

The first one is what the assignment-to-variables gains you, but
I think "**" has a higher precedence than the unary-"-" so it
gets performed first.

I don't have Py3 on my machine here, and 2.5 rejects the first form:

Python 2.5.4 (r254:67916, Nov 19 2009, 19:46:21) [GCC 4.3.4] on

linux2
Type "help", "copyright", "credits" or "license" for more
information.

>>> -(0.1**0.1)
-0.79432823472428149
>>> (-0.1)**0.1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: negative number cannot be raised to a fractional power

But perhaps Py3 changes evaluation, returning an complex number.

-tkc

Daniel Fetchinson

unread,
Feb 11, 2010, 7:49:37 AM2/11/10
to Python
On 2/11/10, Terrence Cole <list...@trainedmonkeystudios.org> wrote:
> Can someone explain to me what python is doing here?
>
> Python 3.1.1 (r311:74480, Feb 3 2010, 13:36:47)
> [GCC 4.3.4] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> -0.1 ** 0.1
> -0.7943282347242815
>>>> a = -0.1; b = 0.1
>>>> a ** b
> (0.7554510437117542+0.2454609236416552j)
>>>> -abs(a ** b)
> -0.7943282347242815
>
> Why does the literal version return the signed magnitude and the
> variable version return a complex?

Try this and think about operator precedence:

Python 3.1.1 (r311:74480, Dec 13 2009, 16:50:25)
[GCC 4.4.2 20091027 (Red Hat 4.4.2-7)] on linux2


Type "help", "copyright", "credits" or "license" for more information.

>>> (-0.1)**0.1
(0.7554510437117542+0.2454609236416552j)
>>>

I.e. -0.1**0.1 is not the same as (-0.1)**0.1, because it's first
0.1**0.1 and then a minus sign.

HTH,
Daniel


--
Psss, psss, put it down! - http://www.cafepress.com/putitdown

Duncan Booth

unread,
Feb 11, 2010, 8:38:46 AM2/11/10
to
Tim Chase <pytho...@tim.thechases.com> wrote:

> But perhaps Py3 changes evaluation, returning an complex number.

Yes, the change is documented at
http://docs.python.org/3.1/reference/expressions.html#the-power-operator

If it is in any of the "What's new in Python x.xx" documents or in a PEP
somewhere I haven't spotted it.

--
Duncan Booth http://kupuguy.blogspot.com

Mark Dickinson

unread,
Feb 11, 2010, 9:21:57 AM2/11/10
to
On Feb 11, 1:38 pm, Duncan Booth <duncan.bo...@invalid.invalid> wrote:

> Tim Chase <python.l...@tim.thechases.com> wrote:
> > But perhaps Py3 changes evaluation, returning an complex number.
>
> Yes, the change is documented athttp://docs.python.org/3.1/reference/expressions.html#the-power-operator

>
> If it is in any of the "What's new in Python x.xx" documents or in a PEP
> somewhere I haven't spotted it.

Not in the 'what's new' documents, as far as I can tell, but this
change was introduced as part of implementing PEP 3141.

http://www.python.org/dev/peps/pep-3141/

Here's an extract from the PEP, describing the 'Complex' abstract base
class:


class Complex(Number):
"""Complex defines the operations that work on the builtin complex
type.

In short, those are: conversion to complex, bool(), .real, .imag,
+, -, *, /, **, abs(), .conjugate(), ==, and !=.

If it is given heterogenous arguments, and doesn't have special
knowledge about them, it should fall back to the builtin complex
type as described below.
"""

<snip lots of other abstractmethods here>

@abstractmethod
def __pow__(self, exponent):
"""a**b; should promote to float or complex when necessary."""
raise NotImplementedError


--
Mark

Robert Kern

unread,
Feb 11, 2010, 10:55:30 AM2/11/10
to pytho...@python.org
On 2010-02-11 06:31 AM, Shashwat Anand wrote:
> Do you really believe that -0.1 ** 0.1 is a valid computational problem
> ? Can you raise a negative number to a fractional power ?
> Output on my console (python 2.6)
>
> >>> -.1 ** .1
> -0.79432823472428149
> >>> a,b = -.1,.1
> >>> a**b

> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> ValueError: negative number cannot be raised to a fractional power
> >>> -abs(a**b)

> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> ValueError: negative number cannot be raised to a fractional power
>
> There is a little issue here that '>>> -.1 ** .1' should give you error
> message. That is it.

No, fractional powers of negative numbers are perfectly valid mathematically.
The result is a complex number. In Python 3 (what the OP is using), this has
been implemented, but not in Python 2.6.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Jussi Piitulainen

unread,
Feb 11, 2010, 11:23:38 AM2/11/10
to
Robert Kern writes:
> On 2010-02-11 06:31 AM, Shashwat Anand wrote:
> > There is a little issue here that '>>> -.1 ** .1' should give you
> > error message. That is it.
>
> No, fractional powers of negative numbers are perfectly valid
> mathematically. The result is a complex number. In Python 3 (what
> the OP is using), this has been implemented, but not in Python 2.6.

Perhaps it should raise a MisleadingSpacingError at compile time. The
error message could recommend - .1**.1, or better -(.1 ** .1).

Grant Edwards

unread,
Feb 11, 2010, 1:43:23 PM2/11/10
to

Didn't we just do this one last week?

--
Grant Edwards grante Yow! Hello? Enema Bondage?
at I'm calling because I want
visi.com to be happy, I guess ...

Terry Reedy

unread,
Feb 11, 2010, 5:52:05 PM2/11/10
to pytho...@python.org
On 2/11/2010 11:23 AM, Jussi Piitulainen wrote:
> Robert Kern writes:
>> On 2010-02-11 06:31 AM, Shashwat Anand wrote:
>>> There is a little issue here that '>>> -.1 ** .1' should give you
>>> error message. That is it.
>>
>> No, fractional powers of negative numbers are perfectly valid
>> mathematically. The result is a complex number. In Python 3 (what
>> the OP is using), this has been implemented, but not in Python 2.6.
>
> Perhaps it should raise a MisleadingSpacingError at compile time.

You forgot the smiley ;-).

> The error message could recommend - .1**.1, or better -(.1 ** .1).

The compiler would never see the difference between -.1 ** .1 and the
first and probably no difference with the second either.


Aahz

unread,
Feb 11, 2010, 9:44:28 PM2/11/10
to
In article <hl1j4a$j61$2...@reader2.panix.com>,

Grant Edwards <inv...@invalid.invalid> wrote:
>
>Didn't we just do this one last week?

Let's do the Time Warp again!
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

"At Resolver we've found it useful to short-circuit any doubt and just
refer to comments in code as 'lies'. :-)"

Jussi Piitulainen

unread,
Feb 12, 2010, 4:40:20 AM2/12/10
to

It could be done the same way that the compiler keeps track of the
source line numbers now: early phases annotate their output with any
information that later phases may need. This error would be detected
during syntactic analysis.

:)

Terry Reedy

unread,
Feb 12, 2010, 11:08:34 AM2/12/10
to pytho...@python.org

There is no error to detect. Sorry, read the manual and either learn or
lookup precedence rules (there is a table in the end of the Expressions
chapter) or use parentheses when not sure.


Jussi Piitulainen

unread,
Feb 12, 2010, 12:48:33 PM2/12/10
to

Thanks.

Albert van der Horst

unread,
Feb 22, 2010, 1:01:44 PM2/22/10
to
In article <mailman.2359.1265890...@python.org>,

Terrence Cole <terr...@zettabytestorage.com> wrote:
>Can someone explain to me what python is doing here?
>
>Python 3.1.1 (r311:74480, Feb 3 2010, 13:36:47)
>[GCC 4.3.4] on linux2
>Type "help", "copyright", "credits" or "license" for more information.
>>>> -0.1 ** 0.1

Python 4.0
Warning: misleading blank space, expected:
- 0.1**0.1

>-0.7943282347242815
>>>> a = -0.1; b = 0.1
>>>> a ** b
>(0.7554510437117542+0.2454609236416552j)
>>>> -abs(a ** b)
>-0.7943282347242815
>
>Why does the literal version return the signed magnitude and the
>variable version return a complex?
>
>Cheers,
>Terrence
>


--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Steven D'Aprano

unread,
Feb 23, 2010, 3:11:52 AM2/23/10
to
On Mon, 22 Feb 2010 18:01:44 +0000, Albert van der Horst wrote:

> In article <mailman.2359.1265890...@python.org>,
> Terrence Cole <terr...@zettabytestorage.com> wrote:
>>Can someone explain to me what python is doing here?
>>
>>Python 3.1.1 (r311:74480, Feb 3 2010, 13:36:47) [GCC 4.3.4] on linux2
>>Type "help", "copyright", "credits" or "license" for more information.
>>>>> -0.1 ** 0.1
>
> Python 4.0
> Warning: misleading blank space, expected:
> - 0.1**0.1
>
>>-0.7943282347242815


Making spaces significant in that fashion is mind-bogglingly awful. Let's
look at a language that does this:

[steve@sylar ~]$ cat ws-example.rb
def a(x=4)
x+2
end

b = 1
print (a + b), (a+b), (a+ b), (a +b), "\n"


[steve@sylar ~]$ ruby ws-example.rb
7773


--
Steven

Mark Dickinson

unread,
Feb 23, 2010, 8:48:09 AM2/23/10
to
On Feb 23, 8:11 am, Steven D'Aprano

<ste...@REMOVE.THIS.cybersource.com.au> wrote:
> Making spaces significant in that fashion is mind-bogglingly awful. Let's
> look at a language that does this:
>
> [steve@sylar ~]$ cat ws-example.rb
> def a(x=4)
>     x+2
> end
>
> b = 1
> print (a + b), (a+b), (a+ b), (a +b), "\n"
>
> [steve@sylar ~]$ ruby ws-example.rb
> 7773

Hmm. That's pretty nasty, all right. Not that Python can claim to be
immune to such behaviour:

>>> 3 .real
3
>>> 3. real
File "<stdin>", line 1
3. real
^
SyntaxError: invalid syntax


Though the fact that one of the cases raises an exception (rather than
silently giving some different behaviour) ameliorates things a bit.

--
Mark

Steven D'Aprano

unread,
Feb 23, 2010, 8:15:40 PM2/23/10
to

It ameliorates it *completely* -- you won't get silent errors in Python
because you add or delete whitespace around a dot.


"I find it amusing when novice programmers believe their main job is
preventing programs from crashing. ... More experienced programmers
realize that correct code is great, code that crashes could use
improvement, but incorrect code that doesn't crash is a horrible
nightmare."

http://www.pphsg.org/cdsmith/types.html


The edge case occurs because dot does double-duty as an operator and as
part of float literals. However, float literals never include whitespace:

>>> 1.5
1.5
>>> 1 . 5


File "<stdin>", line 1

1 . 5
^
SyntaxError: invalid syntax

and likewise for 1. 5 and 1 .5 -- the only way to get a float literal
with a decimal point is by not including whitespace in it. So there is
never any ambiguity about floats. You can even do this:

>>> 1.5.__str__()
'1.5'


And since . is an operator outside of float literals, you can do this:

>>> import sys
>>> sys . platform
'linux2'


although why you'd want to escapes me :)

This actually is a feature, since it is useful when calling methods on
int literals. However this is a very rare thing to do.

--
Steven

Aahz

unread,
Feb 27, 2010, 3:46:38 PM2/27/10
to
In article <pan.2010.02...@REMOVE.THIS.cybersource.com.au>,

Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> wrote:
>
>[steve@sylar ~]$ cat ws-example.rb

Ahhh, you're a Heroes fan. ;-)

"Many customs in this life persist because they ease friction and promote
productivity as a result of universal agreement, and whether they are
precisely the optimal choices is much less important." --Henry Spencer

0 new messages