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

Proposal: Decimal literals in Python.

11 views
Skip to first unread message

Lennart Benschop

unread,
Oct 26, 2007, 4:54:01 AM10/26/07
to
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.

--
Lennart

Ben Finney

unread,
Oct 26, 2007, 5:19:46 AM10/26/07
to
Lennart Benschop <lenn...@xs4all.nl> writes:

> Python has had the Decimal data type for some time now.

Since version 2.4 <URL:http://www.python.org/dev/peps/pep-0327>.

> 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::

>>> from decimal import Decimal
>>> foo = 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")

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.

--
\ "How many people here have telekenetic powers? Raise my hand." |
`\ -- Emo Philips |
_o__) |
Ben Finney

Steven D'Aprano

unread,
Oct 26, 2007, 7:56:56 AM10/26/07
to
On Fri, 26 Oct 2007 19:19:46 +1000, Ben Finney wrote:

>> 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.

You don't like str, int, float, list, set, dict, or bool?

Or for that matter, enum
http://www.python.org/dev/peps/pep-0354/

*wink*


--
Steven.

Ben Finney

unread,
Oct 26, 2007, 9:15:34 AM10/26/07
to
Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:

> On Fri, 26 Oct 2007 19:19:46 +1000, Ben Finney wrote:
> > Nor should we. A function or type name should be short but
> > explicit, and 'Decimal' is about as short as I'd want.
>
> You don't like str, int, float, list, set, dict, or bool?

They'd all make lousy names for a decimal type.

--
\ "Whatever you do will be insignificant, but it is very |
`\ important that you do it." -- Mahatma Gandhi |
_o__) |
Ben Finney

Shane Geiger

unread,
Oct 26, 2007, 3:01:33 PM10/26/07
to Steven D'Aprano, pytho...@python.org

D = lambda x: decimal.Decimal(str(x))

>> D(3.2)
Decimal("3.2")


--
Shane Geiger
IT Director
National Council on Economic Education
sge...@ncee.net | 402-438-8958 | http://www.ncee.net

Leading the Campaign for Economic and Financial Literacy

sgeiger.vcf

Matimus

unread,
Oct 26, 2007, 6:46:03 PM10/26/07
to
> - 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


Ben Finney

unread,
Oct 26, 2007, 7:12:53 PM10/26/07
to
Matimus <mccr...@gmail.com> writes:

> 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.

--
\ "The illiterate of the future will not be the person who cannot |
`\ read. It will be the person who does not know how to learn." |
_o__) -- Alvin Toffler |
Ben Finney

J. Cliff Dyer

unread,
Oct 26, 2007, 7:17:18 PM10/26/07
to python help
- 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.
>
> Matt
My only problem with Decimal("12.34") is the quotation marks. It makes
it look like a string type.

Cheers,
Cliff

J. Cliff Dyer

unread,
Oct 26, 2007, 7:29:47 PM10/26/07
to python help
Ben Finney wrote:
> Matimus <mccr...@gmail.com> writes:
>
>
>> 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
<snip>
>>> type(0b1)
<type 'int'>
>>> type(0o1)
<type 'int'>
>>> type(0x1)
<type 'int'>
>>> assert 0b1 is 0x1
>>>

<hypothetical code>
>>> type(0d1)
<class 'decimal.Decimal'>
>>> assert 0b1 is 0d1
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

Carl Banks

unread,
Oct 26, 2007, 9:55:49 PM10/26/07
to
On Oct 26, 4:54 am, Lennart Benschop <lenna...@xs4all.nl> wrote:
> 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

Carl Banks

unread,
Oct 26, 2007, 10:28:31 PM10/26/07
to
On Oct 26, 7:17 pm, "J. Cliff Dyer" <j...@sdf.lonestar.org> wrote:
> Matimus wrote:
> >> - 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...
>
> - 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

Terry Reedy

unread,
Oct 26, 2007, 11:41:32 PM10/26/07
to pytho...@python.org

"Shane Geiger" <sge...@ncee.net> wrote in message
news:4722398D...@ncee.net...


a buggy hack (copying your top post style)

>>> D(123456789.123456789)
Decimal("123456789.123")

Or what there an unwritten :-)?

Marc 'BlackJack' Rintsch

unread,
Oct 27, 2007, 1:52:04 AM10/27/07
to
On Fri, 26 Oct 2007 19:29:47 -0400, J. Cliff Dyer wrote:

> Ben Finney wrote:
>> 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
> <snip>
>>>> type(0b1)
> <type 'int'>
>>>> type(0o1)
> <type 'int'>
>>>> type(0x1)
> <type 'int'>
>>>> assert 0b1 is 0x1
>>>>

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

Paul Rubin

unread,
Oct 27, 2007, 2:06:52 AM10/27/07
to
Marc 'BlackJack' Rintsch <bj_...@gmx.net> writes:
> >>>> assert 0b1 is 0x1
> 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.

Raymond Hettinger

unread,
Oct 27, 2007, 3:14:48 AM10/27/07
to
On Oct 26, 1:54 am, Lennart Benschop <lenna...@xs4all.nl> wrote:
> 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


MRAB

unread,
Oct 27, 2007, 10:09:44 AM10/27/07
to
On Oct 27, 12:12 am, Ben Finney <bignose+hates-s...@benfinney.id.au>
wrote:

> Matimus <mccre...@gmail.com> writes:
> > 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.

Paul Hankin

unread,
Oct 27, 2007, 11:27:47 AM10/27/07
to

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

--
Paul Hankin

Tim Chase

unread,
Oct 27, 2007, 11:48:10 AM10/27/07
to Paul Hankin, pytho...@python.org
> Even clearer is not to allow octal literals :) Is there *any* use for
> them?

+1

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

-tkc


Dan Bishop

unread,
Oct 27, 2007, 12:16:51 PM10/27/07
to

The mode argument to os.chmod.

Tim Chase

unread,
Oct 27, 2007, 2:28:02 PM10/27/07
to Dan Bishop, pytho...@python.org
>> Even clearer is not to allow octal literals :) Is there *any* use for
>> them?
>
> 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

Marc 'BlackJack' Rintsch

unread,
Oct 27, 2007, 4:01:23 PM10/27/07
to

And the equivalent of ``os.chmod(filename, 0777)`` looks like what!?

Ciao,
Marc 'BlackJack' Rintsch

Message has been deleted

Neil Cerutti

unread,
Oct 27, 2007, 7:10:42 PM10/27/07
to

os.chmod(filename, int('777', 8))

It's good enough for most other bases. ;)

--
Neil Cerutti

Hendrik van Rooyen

unread,
Oct 28, 2007, 3:55:15 AM10/28/07
to Paul Hankin, pytho...@python.org
"Paul Hankin" <p...l.com>wrote:


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

I tend to agree with this point of view - but I fear it will set up a howl
of protest amongst the Brits who cut their teeth on 24 bit ICT/ICL
equipment...

- Hendrik


Tim Roberts

unread,
Oct 28, 2007, 7:22:54 PM10/28/07
to
MRAB <goo...@mrabarnett.plus.com> wrote:

My favorite notation for this comes from Ada, which allows arbitrary bases
from 2 to 16, and allows for underscores within numeric literals:

x23_bin : constant := 2#0001_0111#;
x23_oct : constant := 8#27#;
x23_dec : constant := 10#23#;
x23_hex : constant := 16#17#;

The opportunities for obfuscated coding by writing all constants in base 7
boggle the mind.

I'm not convinced you need delimiters on both ends; I think 16'fffe_3777
would be just as good.

Although, now that I think about the original thread, this doesn't have a
neat solution for the decimal problem...
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Tim Roberts

unread,
Oct 28, 2007, 7:24:51 PM10/28/07
to

As a long-time Control Data employee, I know that 60-bit words and 18-bit
addresses meant that I could do octal arithmetic nearly as fast as decimal.
On the other hand, Python doesn't run on the 6000s...

Gabriel Genellina

unread,
Oct 29, 2007, 1:35:42 AM10/29/07
to pytho...@python.org
En Fri, 26 Oct 2007 23:28:31 -0300, Carl Banks <pavlove...@gmail.com>
escribi�:

> 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).

[OT] Furthermore, the $ sign was used originally to denote "pesos", or
Spanish reals (pieces of eight each). It was later that the US adopted the
sign to denote "dollars" too.

--
Gabriel Genellina

Scott David Daniels

unread,
Jul 14, 2009, 11:44:04 AM7/14/09
to
Tim Roberts wrote:
> My favorite notation for this comes from Ada, which allows arbitrary bases
> from 2 to 16, and allows for underscores within numeric literals:
>
> x23_bin : constant := 2#0001_0111#;
> x23_oct : constant := 8#27#;
> x23_dec : constant := 10#23#;
> x23_hex : constant := 16#17#;
And mine is one w/o the base 10 bias:
.f.123 == 0x123
.7.123 == 0o123
.1.1101 == 0b1101
That is, .<largest allowed digit>.<digits>
-- show the base by showing base-1 in the base.
I actually built this into "OZ," an interpretter.

--Scott David Daniels
Scott....@Acm.Org

MRAB

unread,
Jul 14, 2009, 11:55:18 AM7/14/09
to pytho...@python.org
Smalltalk uses "r" (for "radix"). If we also permit underscores:

x23_bin = 2r0001_0111
x23_oct = 8r27
x23_dec = 10r23
x23_hex = 16r17

0 new messages