469,281 Members | 2,450 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,281 developers. It's quick & easy.

Underscores in Python numbers

I tried finding a discussion around adding the possibility to have
optional underscores inside numbers in Python. This is a popular option
available in several "competing" scripting langauges, that I would love
to see in Python.

Examples:
1_234_567
0xdead_beef
3.141_592

Would appreciate if someone could find a pointer to a previous
discussion on this topic, or add it to a Python-feature-wishlist.

- Gustav

Nov 8 '05
96 5268
Steven D'Aprano <st***@REMOVETHIScyber.com.au> wrote:
That's a tad unfair. Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.


There are plenty of ways to make numeric literals easier to read without
resorting to built-in language support. One way is:

sixTrillion = 6 * 1000 * 1000 * 1000 * 1000

Or, a more general solution might be to write a little factory function
which took a string, stripped out the underscores (or spaces, or commas, or
whatever bit of punctuation turned you on), and then converted the
remaining digit string to an integer. You could then write:

creditCardNumber = myInt ("1234 5678 9012 3456 789")

Perhaps not as convenient as having it built into the language, but
workable in those cases which justify the effort.
Nov 22 '05 #51
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Sat, 19 Nov 2005 13:08:57 -0500, Peter Hansen wrote:
Umm... in other words, "the underscore is under-used so let's assign
some arbitrary meaning to it" (to make the language more like Perl
perhaps?).


+1

I *really* don't like the idea of allowing underscores in numeric
literals. Firstly, for aesthetic reasons: I think 123_456 is seriously
ugly. Secondly, for pragmatic reasons, I think it is too easy to mistype
as 123-456. I know that Python can't protect you from typing 9-1 instead
of 901, but why add special syntax that makes that sort of error MORE
common?)


I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error. This kind of thing might help with
the detecting typos issue, and probably won't be noticed by most
users.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 22 '05 #52
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Sat, 19 Nov 2005 13:08:57 -0500, Peter Hansen wrote:
Umm... in other words, "the underscore is under-used so let's assign
some arbitrary meaning to it" (to make the language more like Perl
perhaps?).


+1

I *really* don't like the idea of allowing underscores in numeric
literals. Firstly, for aesthetic reasons: I think 123_456 is seriously
ugly. Secondly, for pragmatic reasons, I think it is too easy to mistype
as 123-456. I know that Python can't protect you from typing 9-1 instead
of 901, but why add special syntax that makes that sort of error MORE
common?)


I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error. This kind of thing might help with
the detecting typos issue, and probably won't be noticed by most
users.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 22 '05 #53
Mike Meyer <mw*@mired.org> wrote:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three.


That seems a bit silly. Not all numbers are naturally split into groups of
three. Credit card numbers are (typically) split into groups of four.
Account numbers are often split into all sorts of random groupings.
Nov 22 '05 #54
Mike Meyer <mw*@mired.org> wrote:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three.


That seems a bit silly. Not all numbers are naturally split into groups of
three. Credit card numbers are (typically) split into groups of four.
Account numbers are often split into all sorts of random groupings.
Nov 22 '05 #55
Gustav Hållberg wrote:
I tried finding a discussion around adding the possibility to have
optional underscores inside numbers in Python. This is a popular option
available in several "competing" scripting langauges, that I would love
to see in Python.

Examples:
1_234_567
0xdead_beef
3.141_592


I suppose it could be done. OTOH, one could argue that most production
code has no business hardwiring-in numerical constants greater than 999
;-)

Nov 22 '05 #56
Gustav Hållberg wrote:
I tried finding a discussion around adding the possibility to have
optional underscores inside numbers in Python. This is a popular option
available in several "competing" scripting langauges, that I would love
to see in Python.

Examples:
1_234_567
0xdead_beef
3.141_592


I suppose it could be done. OTOH, one could argue that most production
code has no business hardwiring-in numerical constants greater than 999
;-)

Nov 22 '05 #57
Roy Smith <ro*@panix.com> writes:
Mike Meyer <mw*@mired.org> wrote:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three.

That seems a bit silly. Not all numbers are naturally split into groups of
three. Credit card numbers are (typically) split into groups of four.
Account numbers are often split into all sorts of random groupings.


True. But how often do you want to add two account numbers, or
multiply two credit card numbers? Or display them in hex, or otherwise
treat them as something other than a string that happens to be
composed of digits?

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 22 '05 #58
Roy Smith <ro*@panix.com> writes:
Mike Meyer <mw*@mired.org> wrote:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three.

That seems a bit silly. Not all numbers are naturally split into groups of
three. Credit card numbers are (typically) split into groups of four.
Account numbers are often split into all sorts of random groupings.


True. But how often do you want to add two account numbers, or
multiply two credit card numbers? Or display them in hex, or otherwise
treat them as something other than a string that happens to be
composed of digits?

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 22 '05 #59
Peter Hansen <pe***@engcorp.com> writes:
Steven D'Aprano wrote:
Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.


I'm totally unconvinced that this _is_ a real problem, if we define
"real" as being even enough to jiggle my mouse, let alone shattering the
planet.

What examples does anyone have of where it is necessary to define a
large number of large numeric literals? Isn't it the case that other
than the odd constants in various programs, defining a large number of
such values would be better done by creating a data file and parsing
it?


One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
Nov 22 '05 #60
Peter Hansen <pe***@engcorp.com> writes:
Steven D'Aprano wrote:
Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.


I'm totally unconvinced that this _is_ a real problem, if we define
"real" as being even enough to jiggle my mouse, let alone shattering the
planet.

What examples does anyone have of where it is necessary to define a
large number of large numeric literals? Isn't it the case that other
than the odd constants in various programs, defining a large number of
such values would be better done by creating a data file and parsing
it?


One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
Nov 22 '05 #61
Roy Smith wrote:
Steven D'Aprano <st***@REMOVETHIScyber.com.au> wrote:
That's a tad unfair. Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.


There are plenty of ways to make numeric literals easier to read without
resorting to built-in language support. One way is:

sixTrillion = 6 * 1000 * 1000 * 1000 * 1000

Or, a more general solution might be to write a little factory function
which took a string, stripped out the underscores (or spaces, or commas, or
whatever bit of punctuation turned you on), and then converted the
remaining digit string to an integer. You could then write:

creditCardNumber = myInt ("1234 5678 9012 3456 789")


Or alternatively, you could write:

creditCardNumber = int('1234''5678''9012''3456''789')

Nov 22 '05 #62
Roy Smith wrote:
Steven D'Aprano <st***@REMOVETHIScyber.com.au> wrote:
That's a tad unfair. Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.


There are plenty of ways to make numeric literals easier to read without
resorting to built-in language support. One way is:

sixTrillion = 6 * 1000 * 1000 * 1000 * 1000

Or, a more general solution might be to write a little factory function
which took a string, stripped out the underscores (or spaces, or commas, or
whatever bit of punctuation turned you on), and then converted the
remaining digit string to an integer. You could then write:

creditCardNumber = myInt ("1234 5678 9012 3456 789")


Or alternatively, you could write:

creditCardNumber = int('1234''5678''9012''3456''789')

Nov 22 '05 #63
Dan Bishop wrote:
Roy Smith wrote:
creditCardNumber = myInt ("1234 5678 9012 3456 789")


Or alternatively, you could write:

creditCardNumber = int('1234''5678''9012''3456''789')


Or creditCardNumber = int("1234 5678 9012 3456 789".replace(' ',''))

Or make a little function that does the same job and looks cleaner, if
you need this more than once.

But why would anyone want to create numeric literals for credit card
numbers?

-Peter
Nov 22 '05 #64
Dan Bishop wrote:
Roy Smith wrote:
creditCardNumber = myInt ("1234 5678 9012 3456 789")


Or alternatively, you could write:

creditCardNumber = int('1234''5678''9012''3456''789')


Or creditCardNumber = int("1234 5678 9012 3456 789".replace(' ',''))

Or make a little function that does the same job and looks cleaner, if
you need this more than once.

But why would anyone want to create numeric literals for credit card
numbers?

-Peter
Nov 22 '05 #65

Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?

May be for space saving ? But storage space being so cheap, this is not
a very good reason, but still a reason.

Nov 22 '05 #66

Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?

May be for space saving ? But storage space being so cheap, this is not
a very good reason, but still a reason.

Nov 22 '05 #67
Mike Meyer <mw*@mired.org> writes:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error.


Ada allows underscores in numeric literals since 1983, without
enforcing any grouping. The Ruby language allows also this
notation. You may write 1_000_001 or 1000_001 or 10_00_001, etc. (the
same for real numbers...).

When you have the habit to represent literals like that, all other
big numeric literals or workarounds to create grouping seem cryptic.

--
Eric Jacoboni, ne il y a 1435938104 secondes
Nov 22 '05 #68
Mike Meyer <mw*@mired.org> writes:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error.


Ada allows underscores in numeric literals since 1983, without
enforcing any grouping. The Ruby language allows also this
notation. You may write 1_000_001 or 1000_001 or 10_00_001, etc. (the
same for real numbers...).

When you have the habit to represent literals like that, all other
big numeric literals or workarounds to create grouping seem cryptic.

--
Eric Jacoboni, ne il y a 1435938104 secondes
Nov 22 '05 #69
"Dan Bishop" <da*****@yahoo.com> wrote:
creditCardNumber = int('1234''5678''9012''3456''789')


Wow, I didn't know you could do that. That's better than my idea.
Nov 22 '05 #70
"Dan Bishop" <da*****@yahoo.com> wrote:
creditCardNumber = int('1234''5678''9012''3456''789')


Wow, I didn't know you could do that. That's better than my idea.
Nov 22 '05 #71
David M. Cooke wrote:
Peter Hansen <pe***@engcorp.com> writes:

Steven D'Aprano wrote:
Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.


I'm totally unconvinced that this _is_ a real problem, if we define
"real" as being even enough to jiggle my mouse, let alone shattering the
planet.

What examples does anyone have of where it is necessary to define a
large number of large numeric literals? Isn't it the case that other
than the odd constants in various programs, defining a large number of
such values would be better done by creating a data file and parsing
it?

One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Nov 22 '05 #72
David M. Cooke wrote:
Peter Hansen <pe***@engcorp.com> writes:

Steven D'Aprano wrote:
Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.


I'm totally unconvinced that this _is_ a real problem, if we define
"real" as being even enough to jiggle my mouse, let alone shattering the
planet.

What examples does anyone have of where it is necessary to define a
large number of large numeric literals? Isn't it the case that other
than the odd constants in various programs, defining a large number of
such values would be better done by creating a data file and parsing
it?

One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Nov 22 '05 #73
D H
Steve Holden wrote:
David M. Cooke wrote:
One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.


Yes it is.
In that one example he used digit grouping 5 more times than I've
used lambda in my life. Remember people use python as a data format as
well (see for example JSON).
It's a simple harmless change to the parser: ignore underscores or
spaces in numeric literals. As others have mentioned, Ruby supports
this already, as do Ada, Perl, ML variants, VHDL, boo, nemerle, and others.
Nov 22 '05 #74
D H
Steve Holden wrote:
David M. Cooke wrote:
One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.


Yes it is.
In that one example he used digit grouping 5 more times than I've
used lambda in my life. Remember people use python as a data format as
well (see for example JSON).
It's a simple harmless change to the parser: ignore underscores or
spaces in numeric literals. As others have mentioned, Ruby supports
this already, as do Ada, Perl, ML variants, VHDL, boo, nemerle, and others.
Nov 22 '05 #75

D H wrote:
Steve Holden wrote:
David M. Cooke wrote:
One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.


Yes it is.
In that one example he used digit grouping 5 more times than I've
used lambda in my life. Remember people use python as a data format as
well (see for example JSON).
It's a simple harmless change to the parser: ignore underscores or
spaces in numeric literals. As others have mentioned, Ruby supports
this already, as do Ada, Perl, ML variants, VHDL, boo, nemerle, and others.


But that requirement can be served easily with something like this :

a2=my_decimal("-0.16666 66664")

Nov 22 '05 #76

D H wrote:
Steve Holden wrote:
David M. Cooke wrote:
One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.


Yes it is.
In that one example he used digit grouping 5 more times than I've
used lambda in my life. Remember people use python as a data format as
well (see for example JSON).
It's a simple harmless change to the parser: ignore underscores or
spaces in numeric literals. As others have mentioned, Ruby supports
this already, as do Ada, Perl, ML variants, VHDL, boo, nemerle, and others.


But that requirement can be served easily with something like this :

a2=my_decimal("-0.16666 66664")

Nov 22 '05 #77
bo****@gmail.com wrote:
Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?

May be for space saving ? But storage space being so cheap, this is not
a very good reason, but still a reason.


Space saving where? Why would you have any credit card numbers stored
in any application? Even a credit card company isn't going to write
code that has the numbers stored as *literals*!

There's only one place I can think of right now where you might want
that: in automated tests for code that processes credit card numbers.
And you definitely do not need to "save space" in that situation...

-Peter
Nov 22 '05 #78
bo****@gmail.com wrote:
Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?

May be for space saving ? But storage space being so cheap, this is not
a very good reason, but still a reason.


Space saving where? Why would you have any credit card numbers stored
in any application? Even a credit card company isn't going to write
code that has the numbers stored as *literals*!

There's only one place I can think of right now where you might want
that: in automated tests for code that processes credit card numbers.
And you definitely do not need to "save space" in that situation...

-Peter
Nov 22 '05 #79
co**********@physics.mcmaster.ca (David M. Cooke) wrote:
One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.


You have described, if memory serves, a Taylor series, and those
coefficients are 1/3!, 1/5!, 1/7!, etc. What I would do, rather than
embedding the numeric constants in the code, is embed the formula and have
the machine compute the actual values at import time. At the very least,
have them machine generated and saved. You certainly don't want to be
typing in long strings of digits like that.
Nov 22 '05 #80
co**********@physics.mcmaster.ca (David M. Cooke) wrote:
One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.


You have described, if memory serves, a Taylor series, and those
coefficients are 1/3!, 1/5!, 1/7!, etc. What I would do, rather than
embedding the numeric constants in the code, is embed the formula and have
the machine compute the actual values at import time. At the very least,
have them machine generated and saved. You certainly don't want to be
typing in long strings of digits like that.
Nov 22 '05 #81
On Sun, 20 Nov 2005 09:27:28 -0500, Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?

Credit card numbers is not a sensible usage case. Neither are books'
ISBNs, or tax file numbers, or telephone numbers -- these are all
instances where it makes sense to read them from a data file and use a
converter function.

One sensible usage case is numeric calculations, where you often are
using numeric constants in some formula, and those constants may have ten,
twelve, fifteen digits. Being able to group digits makes it considerable
easier to enter the numbers, as well as proof-read your code.

c = 25.173 268 901 910 023

is considerably easier for the human reader to parse than:

c = 25.173268901910023

Calculating the number in place is not an acceptable solution:

c = 25.173 + 268e-3 + 901e-6 + 910e-9 + 23e-12

is bad for a number of reasons:

- it implies c is a calculated sum when it is not;
- it harms comprehension;
- it may very well lose accuracy;
- it is easy to miscalculate and end up with a completely wrong number;
- it complicates and obfuscates the compiled code.

Another sensible usage case is in the interactive interpreter. If you are
using Python interactively, you may wish to use numeric literals with
large numbers of digits. It is not feasible to read them from a data file,
and using a special converter function is impractical and unnecessary.

I don't know whether these two usage cases will be enough to justify
changing the way Python handles numeric literals -- Guido seems quite
conservative in what he adds to the language, so unless there is either
great demand or it scratches a particular itch he has personally, I doubt
it will fly. But we'll never know unless we try, hey? *wink*
--
Steven.

Nov 22 '05 #82
On Sun, 20 Nov 2005 09:27:28 -0500, Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?

Credit card numbers is not a sensible usage case. Neither are books'
ISBNs, or tax file numbers, or telephone numbers -- these are all
instances where it makes sense to read them from a data file and use a
converter function.

One sensible usage case is numeric calculations, where you often are
using numeric constants in some formula, and those constants may have ten,
twelve, fifteen digits. Being able to group digits makes it considerable
easier to enter the numbers, as well as proof-read your code.

c = 25.173 268 901 910 023

is considerably easier for the human reader to parse than:

c = 25.173268901910023

Calculating the number in place is not an acceptable solution:

c = 25.173 + 268e-3 + 901e-6 + 910e-9 + 23e-12

is bad for a number of reasons:

- it implies c is a calculated sum when it is not;
- it harms comprehension;
- it may very well lose accuracy;
- it is easy to miscalculate and end up with a completely wrong number;
- it complicates and obfuscates the compiled code.

Another sensible usage case is in the interactive interpreter. If you are
using Python interactively, you may wish to use numeric literals with
large numbers of digits. It is not feasible to read them from a data file,
and using a special converter function is impractical and unnecessary.

I don't know whether these two usage cases will be enough to justify
changing the way Python handles numeric literals -- Guido seems quite
conservative in what he adds to the language, so unless there is either
great demand or it scratches a particular itch he has personally, I doubt
it will fly. But we'll never know unless we try, hey? *wink*
--
Steven.

Nov 22 '05 #83
On Sun, 20 Nov 2005 15:52:29 -0500, Roy Smith wrote:
You have described, if memory serves, a Taylor series, and those
coefficients are 1/3!, 1/5!, 1/7!, etc. What I would do, rather than
embedding the numeric constants in the code, is embed the formula and have
the machine compute the actual values at import time. At the very least,
have them machine generated and saved. You certainly don't want to be
typing in long strings of digits like that.


Not all numeric constants used have simple formulae, or *any* formulae, or
can be calculated on the fly in any reasonable time. Numeric programming
often uses magic constants which truly are "magic" (in the sense that
where they come from requires deep, difficult, and sometimes hidden
knowledge).

Nobody sensible wants to be typing in long strings of digits, but
sometimes it is unavoidable.

--
Steven.

Nov 22 '05 #84
On Sun, 20 Nov 2005 15:52:29 -0500, Roy Smith wrote:
You have described, if memory serves, a Taylor series, and those
coefficients are 1/3!, 1/5!, 1/7!, etc. What I would do, rather than
embedding the numeric constants in the code, is embed the formula and have
the machine compute the actual values at import time. At the very least,
have them machine generated and saved. You certainly don't want to be
typing in long strings of digits like that.


Not all numeric constants used have simple formulae, or *any* formulae, or
can be calculated on the fly in any reasonable time. Numeric programming
often uses magic constants which truly are "magic" (in the sense that
where they come from requires deep, difficult, and sometimes hidden
knowledge).

Nobody sensible wants to be typing in long strings of digits, but
sometimes it is unavoidable.

--
Steven.

Nov 22 '05 #85
Raymond Hettinger a écrit :
Gustav Hållberg wrote:
I tried finding a discussion around adding the possibility to have
optional underscores inside numbers in Python. This is a popular option
available in several "competing" scripting langauges, that I would love
to see in Python.

Examples:
1_234_567
0xdead_beef
3.141_592

I suppose it could be done. OTOH, one could argue that most production
code has no business hardwiring-in numerical constants greater than 999
;-)

That's what I thought at first, but Steven D'Aprano made some good
points here IMHO, ie :

"""
Not all numeric constants used have simple formulae, or *any* formulae, or
can be calculated on the fly in any reasonable time. Numeric programming
often uses magic constants which truly are "magic" (in the sense that
where they come from requires deep, difficult, and sometimes hidden
knowledge).

Nobody sensible wants to be typing in long strings of digits, but
sometimes it is unavoidable.
"""

and

"""
Another sensible usage case is in the interactive interpreter. If you are
using Python interactively, you may wish to use numeric literals with
large numbers of digits. It is not feasible to read them from a data file,
and using a special converter function is impractical and unnecessary.
"""

So even if it's far from a common use case for *most* Python users, it
may be a common use case for *some* Python users.

Also, someone mentionned the use of Python as a configuration langage -
which is probably a much more common use case.
So FWIW, I'd be +1 on adding it *if and only if*:
- it's trivial to implement [1]
- it doesn't break older code

and +1 on the space as group delimiter BTW.
[1]: I never wrote a language by myself, but I've played a bit with
parsers and lexers, and I _guess_ (which implies I may be wrong !-) it
wouldn't require much work to add support for a "literal numeric
grouping" syntax in Python.
Nov 22 '05 #86
Raymond Hettinger a écrit :
Gustav Hållberg wrote:
I tried finding a discussion around adding the possibility to have
optional underscores inside numbers in Python. This is a popular option
available in several "competing" scripting langauges, that I would love
to see in Python.

Examples:
1_234_567
0xdead_beef
3.141_592

I suppose it could be done. OTOH, one could argue that most production
code has no business hardwiring-in numerical constants greater than 999
;-)

That's what I thought at first, but Steven D'Aprano made some good
points here IMHO, ie :

"""
Not all numeric constants used have simple formulae, or *any* formulae, or
can be calculated on the fly in any reasonable time. Numeric programming
often uses magic constants which truly are "magic" (in the sense that
where they come from requires deep, difficult, and sometimes hidden
knowledge).

Nobody sensible wants to be typing in long strings of digits, but
sometimes it is unavoidable.
"""

and

"""
Another sensible usage case is in the interactive interpreter. If you are
using Python interactively, you may wish to use numeric literals with
large numbers of digits. It is not feasible to read them from a data file,
and using a special converter function is impractical and unnecessary.
"""

So even if it's far from a common use case for *most* Python users, it
may be a common use case for *some* Python users.

Also, someone mentionned the use of Python as a configuration langage -
which is probably a much more common use case.
So FWIW, I'd be +1 on adding it *if and only if*:
- it's trivial to implement [1]
- it doesn't break older code

and +1 on the space as group delimiter BTW.
[1]: I never wrote a language by myself, but I've played a bit with
parsers and lexers, and I _guess_ (which implies I may be wrong !-) it
wouldn't require much work to add support for a "literal numeric
grouping" syntax in Python.
Nov 22 '05 #87

Peter Hansen wrote:
bo****@gmail.com wrote:
Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?
May be for space saving ? But storage space being so cheap, this is not
a very good reason, but still a reason.


Space saving where? Why would you have any credit card numbers stored
in any application? Even a credit card company isn't going to write
code that has the numbers stored as *literals*!

I am not the one asking for it, only guessing the reason and credit
card company does save it in the database. So saving as half byte
numeric(or 64 bit integer) does save a bit of space comparing with
string.

There's only one place I can think of right now where you might want
that: in automated tests for code that processes credit card numbers.
And you definitely do not need to "save space" in that situation...

That usually don't need it as one big number but usually more easier to
code if treating as string(like checksum), something like:

for digits in cc:
checksum += int(digits)

Nov 22 '05 #88

Peter Hansen wrote:
bo****@gmail.com wrote:
Peter Hansen wrote:
But why would anyone want to create numeric literals for credit card
numbers?
May be for space saving ? But storage space being so cheap, this is not
a very good reason, but still a reason.


Space saving where? Why would you have any credit card numbers stored
in any application? Even a credit card company isn't going to write
code that has the numbers stored as *literals*!

I am not the one asking for it, only guessing the reason and credit
card company does save it in the database. So saving as half byte
numeric(or 64 bit integer) does save a bit of space comparing with
string.

There's only one place I can think of right now where you might want
that: in automated tests for code that processes credit card numbers.
And you definitely do not need to "save space" in that situation...

That usually don't need it as one big number but usually more easier to
code if treating as string(like checksum), something like:

for digits in cc:
checksum += int(digits)

Nov 22 '05 #89
On Sun, 20 Nov 2005 15:37:40 +0000, Steve Holden <st***@holdenweb.com> wrote:
David M. Cooke wrote:
Peter Hansen <pe***@engcorp.com> writes:

Steven D'Aprano wrote:

Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.

I'm totally unconvinced that this _is_ a real problem, if we define
"real" as being even enough to jiggle my mouse, let alone shattering the
planet.

What examples does anyone have of where it is necessary to define a
large number of large numeric literals? Isn't it the case that other
than the odd constants in various programs, defining a large number of
such values would be better done by creating a data file and parsing
it?

One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.

Agreed, let the OP hack a special-purpose solution for a special-case problem, e.g.
(tested just enough to show the idea on this post ;-)
def fundef(funsrc, preprocess=None): ... def doprep(f):
... protect_f = {}
... try:
... src = funsrc.lstrip().rstrip()+'\n' # remove leading/trailing blank lines
... exec (preprocess and preprocess(src) or src) in protect_f
... return type(f)(protect_f[f.func_name].func_code,
... f.func_globals, f.func_name, f.func_defaults, f.func_closure)
... except Exception, e:
... raise ValueError, 'Unable to translate %r ... due to\n%s'%(
... funsrc.lstrip().splitlines()[0][:30], '%s: %s'%(e.__class__.__name__, e))
... return doprep
...

Now that decorator allows you to pre-process a function source
(e.g. according to what the OP might want for a preprocess argument):
import re
numgap = re.compile(r'(\d+) (?=\d)')
def prep(s): return numgap.sub(r'\1', s) ...

Then use it on the OP's example [1]
@fundef(""" ... def sinxx(x):
... "computes sin x/x for 0 <= x <= pi/2 to 2e-9"
... a2 = -0.16666 66664
... a4 = 0.00833 33315
... a6 = -0.00019 84090
... a8 = 0.00000 27526
... a10= -0.00000 00239
... x2 = x**2
... return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))
... """, preprocess=prep)
... def sinxx(x): pass # (defines signature and defaults in current scope)
...

[1] Note that no editing of previous source
is required except bracketing like

@fundef("""
<previous source here>
... """, preprocess=prep)
<def-line from previous source with pass after the ':'>

That last line is required for the decorator, but also (I think, not tested) defines
the signature and arg defaults in the current scope, as opposed to where exec compiles
in the decorator.
sinxx <function sinxx at 0x02EFE4C4> import math
def mxx(x): return x and math.sin(x)/x or 1.0 ... sinxx(0), mxx(0) (1.0, 1.0) sinxx(.1), mxx(.1) (0.99833416647076856, 0.99833416646828155) sinxx(.2), mxx(.2) (0.99334665398326816, 0.99334665397530608)
Seems to work, approximately ;-)
@fundef("""

... def poo()
... syntax problems
... """)
... def poo(): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 10, in doprep
ValueError: Unable to translate 'def poo()' ... due to
SyntaxError: invalid syntax (line 1)

Some hope of somewhat useful exceptions too ;-)

Regards,
Bengt Richter
Nov 22 '05 #90
On Sun, 20 Nov 2005 15:37:40 +0000, Steve Holden <st***@holdenweb.com> wrote:
David M. Cooke wrote:
Peter Hansen <pe***@engcorp.com> writes:

Steven D'Aprano wrote:

Dealing with numeric literals with lots of digits is
a real (if not earth-shattering) human interface problem: it is hard for
people to parse long numeric strings.

I'm totally unconvinced that this _is_ a real problem, if we define
"real" as being even enough to jiggle my mouse, let alone shattering the
planet.

What examples does anyone have of where it is necessary to define a
large number of large numeric literals? Isn't it the case that other
than the odd constants in various programs, defining a large number of
such values would be better done by creating a data file and parsing
it?

One example I can think of is a large number of float constants used
for some math routine. In that case they usually be a full 16 or 17
digits. It'd be handy in that case to split into smaller groups to
make it easier to match with tables where these constants may come
from. Ex:

def sinxx(x):
"computes sin x/x for 0 <= x <= pi/2 to 2e-9"
a2 = -0.16666 66664
a4 = 0.00833 33315
a6 = -0.00019 84090
a8 = 0.00000 27526
a10= -0.00000 00239
x2 = x**2
return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))

(or least that's what I like to write). Now, if I were going to higher
precision, I'd have more digits of course.

Right, this is clearly such a frequent use case it's worth changing the
compiler for.

Agreed, let the OP hack a special-purpose solution for a special-case problem, e.g.
(tested just enough to show the idea on this post ;-)
def fundef(funsrc, preprocess=None): ... def doprep(f):
... protect_f = {}
... try:
... src = funsrc.lstrip().rstrip()+'\n' # remove leading/trailing blank lines
... exec (preprocess and preprocess(src) or src) in protect_f
... return type(f)(protect_f[f.func_name].func_code,
... f.func_globals, f.func_name, f.func_defaults, f.func_closure)
... except Exception, e:
... raise ValueError, 'Unable to translate %r ... due to\n%s'%(
... funsrc.lstrip().splitlines()[0][:30], '%s: %s'%(e.__class__.__name__, e))
... return doprep
...

Now that decorator allows you to pre-process a function source
(e.g. according to what the OP might want for a preprocess argument):
import re
numgap = re.compile(r'(\d+) (?=\d)')
def prep(s): return numgap.sub(r'\1', s) ...

Then use it on the OP's example [1]
@fundef(""" ... def sinxx(x):
... "computes sin x/x for 0 <= x <= pi/2 to 2e-9"
... a2 = -0.16666 66664
... a4 = 0.00833 33315
... a6 = -0.00019 84090
... a8 = 0.00000 27526
... a10= -0.00000 00239
... x2 = x**2
... return 1. + x2*(a2 + x2*(a4 + x2*(a6 + x2*(a8 + x2*a10))))
... """, preprocess=prep)
... def sinxx(x): pass # (defines signature and defaults in current scope)
...

[1] Note that no editing of previous source
is required except bracketing like

@fundef("""
<previous source here>
... """, preprocess=prep)
<def-line from previous source with pass after the ':'>

That last line is required for the decorator, but also (I think, not tested) defines
the signature and arg defaults in the current scope, as opposed to where exec compiles
in the decorator.
sinxx <function sinxx at 0x02EFE4C4> import math
def mxx(x): return x and math.sin(x)/x or 1.0 ... sinxx(0), mxx(0) (1.0, 1.0) sinxx(.1), mxx(.1) (0.99833416647076856, 0.99833416646828155) sinxx(.2), mxx(.2) (0.99334665398326816, 0.99334665397530608)
Seems to work, approximately ;-)
@fundef("""

... def poo()
... syntax problems
... """)
... def poo(): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 10, in doprep
ValueError: Unable to translate 'def poo()' ... due to
SyntaxError: invalid syntax (line 1)

Some hope of somewhat useful exceptions too ;-)

Regards,
Bengt Richter
Nov 22 '05 #91
On Sun, 20 Nov 2005 15:50:10 +0100, Eric Jacoboni <ja**@neottia.net> wrote:
Mike Meyer <mw*@mired.org> writes:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error.


Ada allows underscores in numeric literals since 1983, without
enforcing any grouping. The Ruby language allows also this
notation. You may write 1_000_001 or 1000_001 or 10_00_001, etc. (the
same for real numbers...).

When you have the habit to represent literals like that, all other
big numeric literals or workarounds to create grouping seem cryptic.

--
Eric Jacoboni, ne il y a 1435938104 secondes

Um, about your sig ... ;-)

Regards,
Bengt Richter
Nov 22 '05 #92
On Sun, 20 Nov 2005 15:50:10 +0100, Eric Jacoboni <ja**@neottia.net> wrote:
Mike Meyer <mw*@mired.org> writes:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error.


Ada allows underscores in numeric literals since 1983, without
enforcing any grouping. The Ruby language allows also this
notation. You may write 1_000_001 or 1000_001 or 10_00_001, etc. (the
same for real numbers...).

When you have the habit to represent literals like that, all other
big numeric literals or workarounds to create grouping seem cryptic.

--
Eric Jacoboni, ne il y a 1435938104 secondes

Um, about your sig ... ;-)

Regards,
Bengt Richter
Nov 22 '05 #93
On Sun, 20 Nov 2005 15:50:10 +0100, Eric Jacoboni <ja**@neottia.net> wrote:
Mike Meyer <mw*@mired.org> writes:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error.
Ada allows underscores in numeric literals since 1983, without
enforcing any grouping. The Ruby language allows also this
notation. You may write 1_000_001 or 1000_001 or 10_00_001, etc. (the
same for real numbers...).

Actually, I guess I could be convinced, even though I posted a
you-can-do-this-now decorator to bracket the op's desired function defs.
When you have the habit to represent literals like that, all other
big numeric literals or workarounds to create grouping seem cryptic.

--
Eric Jacoboni, ne il y a 1435938104 secondes

My previous smiley re your sig in this thread context still applies ;-)

Regards,
Bengt Richter
Nov 22 '05 #94
On Sun, 20 Nov 2005 15:50:10 +0100, Eric Jacoboni <ja**@neottia.net> wrote:
Mike Meyer <mw*@mired.org> writes:
I've seen at least one language (forget which one) that allowed such
separators, but only for groups of three. So 123_456 would be valid,
but 9_1 would be a syntax error.
Ada allows underscores in numeric literals since 1983, without
enforcing any grouping. The Ruby language allows also this
notation. You may write 1_000_001 or 1000_001 or 10_00_001, etc. (the
same for real numbers...).

Actually, I guess I could be convinced, even though I posted a
you-can-do-this-now decorator to bracket the op's desired function defs.
When you have the habit to represent literals like that, all other
big numeric literals or workarounds to create grouping seem cryptic.

--
Eric Jacoboni, ne il y a 1435938104 secondes

My previous smiley re your sig in this thread context still applies ;-)

Regards,
Bengt Richter
Nov 22 '05 #95
Peter Hansen>Or maybe one should instead interpret this as "numeric
literals need more bells and whistles, and I don't care which of these
two we add, but we have to do *something*!". :-)

The purpose of my words was: when you think about adding a new
syntax/functionality to a language, you have to think well if the same
syntax can be used for something more important or more natural for it,
so later you can avoid later problems and silly compromises.

Bye,
bearophile

Nov 22 '05 #96
Peter Hansen>Or maybe one should instead interpret this as "numeric
literals need more bells and whistles, and I don't care which of these
two we add, but we have to do *something*!". :-)

The purpose of my words was: when you think about adding a new
syntax/functionality to a language, you have to think well if the same
syntax can be used for something more important or more natural for it,
so later you can avoid later problems and silly compromises.

Bye,
bearophile

Nov 22 '05 #97

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.