Proposal: Decimal literals in Python.

L

Lennart Benschop

Python has had the Decimal data type for some time now. The Decimal data
type is ideal for financial calculations. Using this data type would be
more intuitive to computer novices than float as its rounding behaviour
matches more closely what humans expect. More to the point: 0.1 and 0.01
are exact in Decimal and not exact in float.

Unfortunately it is not very easy to access the Decimal data type. To obtain
the decimal number 12.34 one has to do something like this:

import decimal
x=decimal.Decimal("12.34")

Of course we can intruduce a single character function name as an alias for
the Decimal type constructor, but even then we have to use both parentheses
and quotes for each and every decimal constant. We cannot make it shorter
than D("12.34")

With Python 3000 major changes to the language are carried out anyway. My
proposal would require relatively minor changes.

My proposal:
- Any decimal constant suffixed with the letter "D" or "d" will be
interpreted as a literal of the Decimal type. This also goes for
decimal constants with exponential notation.

Examples of decimal literals:
1d
12.34d
1e-3d (equivalent to 0.001d)
1e3d (same value as 1000d, but without trailing zeros).
1.25e5d (same value as 125000d but without trailing zeros).

When we print a decimal number or convert it to a string with str(), a
trailing d should not be added. The repr function does yield strings with a
trailing d.

When decimal numbers are converted from strings, both numbers with and
without a trailing d should be accepted.

If we have decimal literals in the core language, we should probably have a
type constructor in the core namespace, e.g. dec() along with int()
and float(). We then need the decimal module only for the more advanced
stuff like setcontext.

Pros:
- the Decimal data type will be more readily accessible, especially
for novices.
- Traling characters at the end of a literal are already used (the L
for long).
- It does not conflict with the syntax of other numeric constants or
language constructs.
- It does not change the meaning of existing valid literal constants.
Constants that used to be float will continue to do so.

Cons:
- The lexical scanner of the Python interpreter will be slightly more
complex.
- The d suffix for constants with exponential notation is ugly.
- Decimal numbers with exponentail notation like 2e5d could be mistaken
for hex (by humans, not by the parser as hex requires the 0x prefix).
- It requires the decimal module to be part of the core Python
interpreter.
 
B

Ben Finney

Lennart Benschop said:
Python has had the Decimal data type for some time now.

Since version 2.4 said:
Unfortunately it is not very easy to access the Decimal data
type. To obtain the decimal number 12.34 one has to do something
like this:

import decimal
x=decimal.Decimal("12.34")

Slightly nicer, if you need to create a lot of them::
Of course we can intruduce a single character function name as an
alias for the Decimal type constructor, but even then we have to use
both parentheses and quotes for each and every decimal constant. We
cannot make it shorter than D("12.34")

Nor should we. A function or type name should be short but explicit,
and 'Decimal' is about as short as I'd want.
With Python 3000

"Python 3000" is now in beta development, and is called Python version
3.0.
major changes to the language are carried out anyway.

All of which have been decided for some time now. It's rather too late
to introduce behaviour changes and hope for them to be in Python 3.0.
My proposal:

Feel free to file an actual proposal using the PEP process. You might
want to refer to the PEP that introduced the Decimal type for
inspiration.
 
M

Matimus

- Traling characters at the end of a literal are already used (the L
for long).

The trailing L is going away in Python 3.0. For your consideration may
I suggest a '$' prefix. Though, I'm not sure I even support the idea
of a decimal literal, and I'm not even sure if I support the idea of
using a prefix '$' to identify that literal, it seems somewhat
fitting.

So...
Decimal("12.34") -> $12.34

Pros:
- Easier to see than appended character (I think)
- Notation is fitting when dealing with monetary values
- Easy to remember
Cons:
- Maybe too clever for its own good. Some people may be confused to
find out that it isn't actually a monetary type.

I'm sure there are more...

Matt
 
B

Ben Finney

Matimus said:
The trailing L [for 'long' literals] is going away in Python 3.0.

Yes. On the other hand, we are gaining '0bNNNN' for binary literals,
to go along with '0oNNNN' for octal and '0xNNNN' for hexadecimal.

So, the original poster might get further by proposing an '0dNNN.NNN'
syntax for 'decimal.Decimal' literals. At least the syntax would be
consistent and wouldn't add a new punctuation character to the
language...
For your consideration may I suggest a '$' prefix.

.... unlike this one.
 
J

J. Cliff Dyer

Matimus said:
The trailing L is going away in Python 3.0. For your consideration may
I suggest a '$' prefix. Though, I'm not sure I even support the idea
of a decimal literal, and I'm not even sure if I support the idea of
using a prefix '$' to identify that literal, it seems somewhat
fitting.

So...
Decimal("12.34") -> $12.34

Pros:
- Easier to see than appended character (I think)
- Notation is fitting when dealing with monetary values
- Easy to remember
Cons:
- Maybe too clever for its own good. Some people may be confused to
find out that it isn't actually a monetary type.
I'm sure there are more...
- Too U.S. centric. Euro would be a slight improvement, as it doesn't
privilege one country, but still too region-centric. Generic currency
marker from ISO 8859-1 would be even less unnecessarily specific, but
also too obscure.
- Looks funny if you use more or fewer than 2 decimal places.
- Sacrifices clarity of meaning for brevity.
My only problem with Decimal("12.34") is the quotation marks. It makes
it look like a string type.

Cheers,
Cliff
 
J

J. Cliff Dyer

Ben said:
The trailing L [for 'long' literals] is going away in Python 3.0.

Yes. On the other hand, we are gaining '0bNNNN' for binary literals,
to go along with '0oNNNN' for octal and '0xNNNN' for hexadecimal.

So, the original poster might get further by proposing an '0dNNN.NNN'
syntax for 'decimal.Decimal' literals.
It would rather be remarkably inconsistent and confusing.

Python 3.0a1 (py3k:57844, Aug 31 2007, 16:54:27) [MSC v.1310 32 bit
(Intel)] on win32
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
assert 0b1 is 0d1
AssertionError

</hypothetical code>

It would also be unkind to people with dyslexia.

Cheers,
Cliff
 
C

Carl Banks

Python has had the Decimal data type for some time now. The Decimal data
type is ideal for financial calculations. Using this data type would be
more intuitive to computer novices than float as its rounding behaviour
matches more closely what humans expect. More to the point: 0.1 and 0.01
are exact in Decimal and not exact in float.

Unfortunately it is not very easy to access the Decimal data type. To obtain
the decimal number 12.34 one has to do something like this:

import decimal
x=decimal.Decimal("12.34")

Of course we can intruduce a single character function name as an alias for
the Decimal type constructor, but even then we have to use both parentheses
and quotes for each and every decimal constant. We cannot make it shorter
than D("12.34")

With Python 3000 major changes to the language are carried out anyway. My
proposal would require relatively minor changes.

My proposal:
- Any decimal constant suffixed with the letter "D" or "d" will be
interpreted as a literal of the Decimal type. This also goes for
decimal constants with exponential notation.

This brings something to mind.

One thing I've always thought would be cool would be to have
programmable literals. (Note: Python 3 has a ban on programmable
syntax, and this is clearly falls under that umbrella, although in a
limited form. So this is not a proposal of any sort, just idle
chatter. :)

The idea is: the compiler would see the literal, evaluate it at
compile time, and marshal the evaluated value into the *.pyc file.
More easily said than done, yes, and I'm aware of the issues in doing
that. But it'd be pretty useful, I'd think.

Decimal literals has been mentioned.

In fact it could benefit a lot of numeric objects, such as those in
gmpy.

Regular expressions. A significant speed deficiency of regexps in
Python relative to Perl is that Python has to compile regular
expressions every time the program is invoked. What if you could
compile the regexp at, you know, compile time, and marshall the
compiled state? It could speed things up a bit, especially for small,
regexp heavy scripts.

Oh, well, you get the idea. It's not going to happen, but it'd be
cool while not anything crucial.


Carl Banks
 
C

Carl Banks

- Too U.S. centric. Euro would be a slight improvement, as it doesn't
privilege one country, but still too region-centric. Generic currency
marker from ISO 8859-1 would be even less unnecessarily specific, but
also too obscure.

FYI: The $ sign is used to denote currency in many countries; as a
rule of thumb countties that call their currency "dollars" or "pesos"
use the $. So Mexico, Canada, Australia, much of Latin America, much
of the Pacific, not to mention countries in Africa (Zimbabwe) and Asia
(Singapore).

It's certainly less region-specific than the Euro is.


Carl Banks
 
T

Terry Reedy

a buggy hack (copying your top post style)
Decimal("123456789.123")

Or what there an unwritten :)?

| D = lambda x: decimal.Decimal(str(x))
|
| >> D(3.2)
| Decimal("3.2")
 
M

Marc 'BlackJack' Rintsch

Ben said:
So, the original poster might get further by proposing an '0dNNN.NNN'
syntax for 'decimal.Decimal' literals.
It would rather be remarkably inconsistent and confusing.

Python 3.0a1 (py3k:57844, Aug 31 2007, 16:54:27) [MSC v.1310 32 bit
(Intel)] on win32

That this doesn't raise `AssertionError` is an implementation detail.
It's not guaranteed the two objects are really the same.

Ciao,
Marc 'BlackJack' Rintsch
 
P

Paul Rubin

Marc 'BlackJack' Rintsch said:
That this doesn't raise `AssertionError` is an implementation detail.
It's not guaranteed the two objects are really the same.

I think Ben is getting at 0b1 and 0x1 being the same type, while the
proposed 0d1 is a different type. I don't see anything wrong with 1d.
We already have 1j and I don't think that's going away in 3.0.
 
R

Raymond Hettinger

My proposal:
- Any decimal constant suffixed with the letter "D" or "d" will be
interpreted as a literal of the Decimal type. This also goes for
decimal constants with exponential notation.

There's nothing new here that hasn't already been proposed and
discussed on python-dev. There were no major objections to the idea;
however, it will need to wait until there is a good C implementation
of the decimal module (which is in the works but coming along very,
very slowly). Also, once we have a C coded decimal object, further
work would be needed to make it integrate well with the rest of the
language (i.e. making sure that everything allows numeric inputs can
handle a decimal object as a possible input).

FWIW, using the decimal module is not at all as onerous as the OP
makes it sound. I write:

from decimal import Decimal as D
print D(1) / D(7) + D('0.123456')

That isn't much of a burden compared with:

print 1d / 7d + 0.123456d

You would still need to import decimal so you can set the context
parameters (like precision and rounding).

Also, most non-toy scripts have *very* few literals in them; instead,
the decimal values arise from calculations, user inputs, and file of
data. Casting those to the correct type is really no more difficult
that it is with other types:

s = raw_input('Input temperature')
print int(s), Decimal(s), float(s)

Raymond
 
M

MRAB

Matimus said:
The trailing L [for 'long' literals] is going away in Python 3.0.

Yes. On the other hand, we are gaining '0bNNNN' for binary literals,
to go along with '0oNNNN' for octal and '0xNNNN' for hexadecimal.

So, the original poster might get further by proposing an '0dNNN.NNN'
syntax for 'decimal.Decimal' literals. At least the syntax would be
consistent and wouldn't add a new punctuation character to the
language...
[snip]
Some languages have or permit 0qNNNN or 0QNNNN for octal to reduce the
chance of confusion of 'O' (oh) with '0' (zero) in uppercase, eg.
0Q123 is clearer than 0O123 (0 oh 123), although lowercase is better,
eg. 0q123 or 0o123.
 
P

Paul Hankin

The trailing L [for 'long' literals] is going away in Python 3.0.
Yes. On the other hand, we are gaining '0bNNNN' for binary literals,
to go along with '0oNNNN' for octal and '0xNNNN' for hexadecimal.
So, the original poster might get further by proposing an '0dNNN.NNN'
syntax for 'decimal.Decimal' literals. At least the syntax would be
consistent and wouldn't add a new punctuation character to the
language...

[snip]
Some languages have or permit 0qNNNN or 0QNNNN for octal to reduce the
chance of confusion of 'O' (oh) with '0' (zero) in uppercase, eg.
0Q123 is clearer than 0O123 (0 oh 123), although lowercase is better,
eg. 0q123 or 0o123.

Even clearer is not to allow octal literals :) Is there *any* use for
them?
 
T

Tim Chase

Even clearer is not to allow octal literals :) Is there *any* use for

+1

I find that anything I have even the remotest inkling of using
octal for can be done just as easily with hex.

-tkc
 
D

Dan Bishop

The trailing L [for 'long' literals] is going away in Python 3.0.
Yes. On the other hand, we are gaining '0bNNNN' for binary literals,
to go along with '0oNNNN' for octal and '0xNNNN' for hexadecimal.
So, the original poster might get further by proposing an '0dNNN.NNN'
syntax for 'decimal.Decimal' literals. At least the syntax would be
consistent and wouldn't add a new punctuation character to the
language...
[snip]
Some languages have or permit 0qNNNN or 0QNNNN for octal to reduce the
chance of confusion of 'O' (oh) with '0' (zero) in uppercase, eg.
0Q123 is clearer than 0O123 (0 oh 123), although lowercase is better,
eg. 0q123 or 0o123.

Even clearer is not to allow octal literals :) Is there *any* use for
them?

The mode argument to os.chmod.
 
T

Tim Chase

Even clearer is not to allow octal literals :) Is there *any* use for
The mode argument to os.chmod.

You mean instead of

import this
os.chmod(filename, os.R_OK | os.W_OK | os.X_OK)

which explicitly (rather than implicitly) spells it out?

-tkc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top