Why does exponential notation with decimal values fail? [closed] - python

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
Conventionally 1e3 means 10**3.
>>> 1e3
1000.0
>>> 10**3
1000
Similar case is exp(3) compared to e**3.
>>> exp(3)
20.085536923187668
>>> e**3
20.085536923187664
However now notice if the exponent is a float value:
>>> exp(3.1)
22.197951281441636
>>> e**3.1
22.197951281441632
which is fine. Now for the first example:
>>> 1e3.1
File "<stdin>", line 1
1e3.1
^
SyntaxError: invalid syntax
>>> 10**3.1
1258.9254117941675
which shows Python does not like 1e3.1, Fortran too.
Regardless it could be a standard (!) why it is like that?

The notation with the e is a numeric literal, part of the lexical syntax of many programming languages, based on standard form/scientific notation.
The purpose of this notation is to allow you to specify very large/small numbers by shifting the point position. It's not intended to allow you to encode multiplication by some arbitrary power of 10 into numeric literals. Therefore, that point and the following digits aren't even recognised as part of the numeric literal token.
If you want arbitrary powers, as you've found, there are math functions and operators that do the job. Unlike a numeric literal, you even get to determine the parameter values at run-time.

From the docs:
sign ::= '+' | '-'
digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
indicator ::= 'e' | 'E'
digits ::= digit [digit]...
decimal-part ::= digits '.' [digits] | ['.'] digits
exponent-part ::= indicator [sign] digits #no dots allowed here

You seem to be conflating syntax for literals with operators. While you can claim that 1e3.1 follows your "convention" it should be quite clear that 1e3.1 is not a valid literal expression to the Python interpeter. The language has a defined standard grammar, and that grammer doesn't support floating point literal expressions as "exponents" for its numeric literals.
The "e" in a Python numeric literal is not an operator (any more than the decimal point would be). So your expectation that Python's literal syntax should support some "convention" ... based on some pattern you've divined ... is not particularly reasonable.

Related

Why does `'{x[1:3]}'.format(x="asd")` cause a TypeError?

Consider this:
>>> '{x[1]}'.format(x="asd")
's'
>>> '{x[1:3]}'.format(x="asd")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: string indices must be integers
What could be the cause for this behavior?
An experiment based on your comment, checking what value the object's __getitem__ method actually receives:
class C:
def __getitem__(self, index):
print(repr(index))
'{c[4]}'.format(c=C())
'{c[4:6]}'.format(c=C())
'{c[anything goes!##$%^&]}'.format(c=C())
C()[4:6]
Output (Try it online!):
4
'4:6'
'anything goes!##$%^&'
slice(4, 6, None)
So while the 4 gets converted to an int, the 4:6 isn't converted to slice(4, 6, None) as in usual slicing. Instead, it remains simply the string '4:6'. And that's not a valid type for indexing/slicing a string, hence the TypeError: string indices must be integers you got.
Update:
Is that documented? Well... I don't see something really clear, but #GACy20 pointed out something subtle. The grammar has these rules
field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
element_index ::= digit+ | index_string
index_string ::= <any source character except "]"> +
Our c[4:6] is the field_name, and we're interested in the element_index part 4:6. I think it would be clearer if digit+ had its own rule with meaningful name:
field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
element_index ::= index_integer | index_string
index_integer ::= digit+
index_string ::= <any source character except "]"> +
I'd say having index_integer and index_string would more clearly indicate that digit+ is converted to an integer (instead of staying a digit string), while <any source character except "]"> + would stay a string.
That said, looking at the rules as they are, perhaps we should think "what would be the point of separating the digits case out of the any-characters case which would match it as well?" and think that the point is to treat pure digits differently, presumably to convert them to an integer. Or maybe some other part of the documentation even states that digit or digits+ in general gets converted to an integer.
'{x[1]}'.format(x="asd") the [1] syntax here is not the "normal" string indexing syntax, even if in this case it appears to be working the same way.
It is using the Format Specification Mini-Language. The same mechanism that allows for passing objects and accessing an arbitrary attribute inside the formatted string (eg '{x.name}'.format(x=some_object)).
This "fake" indexing syntax also allows to pass indexable objects to format and directly getting the element you want from within the formatted string:
'{x[0]}'.format(x=('a', 'tuple'))
# 'a'
'{x[1]}'.format(x=('a', 'tuple'))
# 'tuple'
The only reference (that I could find, at least) for this in the docs is this paragraph:
The field_name itself begins with an arg_name that is either a number or a keyword. If it’s a number, it refers to a positional argument, and if it’s a keyword, it refers to a named keyword argument. If the numerical arg_names in a format string are 0, 1, 2, … in sequence, they can all be omitted (not just some) and the numbers 0, 1, 2, … will be automatically inserted in that order. Because arg_name is not quote-delimited, it is not possible to specify arbitrary dictionary keys (e.g., the strings '10' or ':-]') within a format string. The arg_name can be followed by any number of index or attribute expressions. An expression of the form '.name' selects the named attribute using getattr(), while an expression of the form '[index]' does an index lookup using __getitem__().
While it mentions
while an expression of the form '[index]' does an index lookup using __getitem__().
it does not mention anything about slicing syntax not being supported.
For me this feels like an oversight in the docs, especially because '{x[1:3]}'.format(x="asd") generates such a cryptic error message, and even more so due to __getitem__ already supporting slicing.

In Python, What is the process and importance of 'a' > 'A' being True?

I've tried various search terms in Google and I have tried to find an answer from the official docs but I cannot find a reasonable (read: understandable) explanation why this is the case in Python.
I understand that it's something to do with lexicographical order.
The expression 'a' > 'A' is regarded as True
But why is this the case? Or rather, why does this need to be the case?
Sorry if this is phrased badly, this is my first ever question on this site.
This should make the ordering clearer:
>>> ord('a')
97
>>> ord('A')
65
>>> ord('a') > ord('A')
True
The character code for 'a' is greater than the one for 'A'.
ord('a') returns an integer representing the Unicode code. The ord() is the inverse of chr().
The Unicode standard describes how characters are represented by code points. A code point is an integer value, usually denoted in base 16. In the standard, a code point is written using the notation U+12CA to mean the character with value 0x12ca (4,810 decimal). The Unicode standard contains a lot of tables listing characters and their corresponding code points:
0061 'a'; LATIN SMALL LETTER A
0062 'b'; LATIN SMALL LETTER B
0063 'c'; LATIN SMALL LETTER C
...
007B '{'; LEFT CURLY BRACKET
Read more here: https://docs.python.org/3.3/howto/unicode.html

Negative constants and operator precedence

I've been programming in Python for years but something extremely trivial has surprised me:
>>> -1 ** 2
-1
Of course, squaring any negative real number should produce a positive result. Probably Python's math is not completely broken. Let's look at how it parsed this expression:
>>> ast.dump(ast.parse('-1 ** 2').body[0])
Expr(
value=UnaryOp(
op=USub(),
operand=BinOp(
left=Num(n=1),
op=Pow(),
right=Num(n=2)
)
)
)
Ok, so it is treating it as if I had written -(1 ** 2). But why is the - prefix to 1 being treated as a separate unary subtraction operator, instead of the sign of the constant?
Note that the expression -1 is not parsed as the unary subtraction of the constant 1, but just the constant -1:
>>> ast.dump(ast.parse('-1').body[0])
Expr(
value=Num(n=-1)
)
The same goes for -1 * 2, even though it is syntactically nearly identical to the first expression.
>>> ast.dump(ast.parse('-1 * 2').body[0])
Expr(
value=BinOp(
left=Num(n=-1),
op=Mult(),
right=Num(n=2)
)
)
This behavior turns out to be common to many languages including perl, PHP, and Ruby.
It behaves just like the docs explain here:
2.4.4. Numeric literals
[...] Note that numeric literals do not include a sign; a phrase like -1 is actually an expression composed of the unary operator - and the literal 1.
and here:
6.5. The power operator
The power operator binds more tightly than unary operators on its
left; [...]
See also the precedence table from this part. Here is the relevant part from that table:
Operator | Description
-------------|---------------------------------
* | Multiplication, ...
+x, -x, ~x | Positive, negative, bitwise NOT
** | Exponentiation
This explains why the parse tree is different between the ** and * examples.

what is the meaning of float.__pos__? [duplicate]

This question already has answers here:
What's the purpose of the + (pos) unary operator in Python?
(7 answers)
Closed 8 years ago.
I am writing a function computing like eval. When I come to float.__pos__ ,I really don't Know why there exists such a useless function. Because:
>>> float.__pos__(-1.0)
-1.0
>>> float.__pos__(1.0)
1.0
while float.__neg__ is totally different:
>>> float.__neg__(1.0)
-1.0
So what is the meaning of float.__pos__?
>>> help(float.__pos__)
Help on wrapper_descriptor:
__pos__(...)
x.__pos__() <==> +x
It's the "unary plus" operator, invoked when you do +x with x a float. It basically does nothing for floats, as you've discovered ;-) However, you could define a subclass that did something non-trivial with it. That's why it's there.
The __pos__ method defines the effect of the unary + operator for any object.
As Tim Peters mentions, it has no effect for floats.
See What's the purpose of the + (pos) unary operator in Python? for an example where it's used to do something.
Python has a unary negation operator to negate numbers, as you're probably well aware:
>>> x = 5
>>> print(-x)
-5
>>> x = -5
>>> print(-x)
5
Say you're making a list of numbers, though. It might be more consistent if you prefixed the positive ones with a +, so Python has a unary + operator, too:
>>> numbers = [-3, -2, -1, 0, +1, +2, +3]
When you use the unary + operator on a number, you're right that it doesn't do anything; it's there just for consistency.
Now when you consider that in Python you can override operators on types, of course you'd need a __neg__ to negate an instance of that type. Python just decided to be consistent by also having a __pos__ to…not negate an instance of that type. float, like all other types overriding these operators, follow this protocol, and float's implementation of __pos__ is just the identity function.

Fastest way to concatenate two numbers in Python [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
suppose you have two strings (with digits only) in Python, say string a and string b. What is the fastest way to produce the number c = a.b (hence, a integer part, and b decimal part)?
If quicker is meant in terms of speed, my usage recommends me this:
float("%s.%s"% ("12", "345"))
timeit results:
>>> timeit.Timer('float("%s.%s"% ("12", "245"))').timeit()
0.39421987533569336
>>> timeit.Timer('float("{0}.{1}".format("12", "245"))').timeit()
0.573634147644043
Primitive formatting (might be the quickest? ): float(str(a) + '.' + str(b))
This solution doesn't need to parse a format string.
[Added as the answer to the disbelievers]
>>> timeit.Timer('float("%s.%s"% ("12", "245"))').timeit()
1.147318164738806
>>> timeit.Timer('float("{0}.{1}".format("12", "245"))').timeit()
1.5033958226534452
>>> timeit.Timer('float("12" + "." + "245")').timeit()
0.6646503955111598
Part of the explanation could be that you can always write %s even for the int arguments. It is likely that there is an extra string conversion when formatted via % or via .format().
Using float and format.
>>> a, b = '12', '345'
>>> float('{0}.{1}'.format(a, b))
12.345
EDIT: Cannot claim this is fastest (as I haven't tested the speed w.r.t. other solutions), but does get the job done.
This will raise a ValueError if a or b cannot be converted to integers (if not only digits for example):
float('%d.%d' % (int(a), int(b)))
(tested on Python 2.7)

Categories

Resources