471,320 Members | 2,068 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,320 software developers and data experts.

About Rational Number (PEP 239/PEP 240)

Lie
I'm very surprised actually, to see that Python rejected the use of
fractional/rational numbers. However, when I read the PEP, I know
exactly why the proposal was rejected: People compared fractions with
integers, while it should be more fairly compared to floats.

Arguments against:
- When I use the result of / as a sequence index, it's usually an
error which should not be hidden by making the program working for
some data, since it will break for other data.
----In Python 3 (and 2 w/ __future__), the / operator would always
return floats, and floats is invalid as sequence index, even if the
value of the float is whole. Since fractions is created with the /
operator on two integers, the behavior of fractions should mimics
float. So putting fractional type as sequence index should always be
considered as error (exception), a behavior consistent with floats.
Thus, the arguments specified above has turned invalid, at least in
Python 3.
- (this assumes the same type for them:) Int is a good type in itself,
not to be mixed with rationals. The fact that something is an integer
should be expressible as a statement about its type. Many operations
require ints and don't accept rationals. It's natural to think about
them as about different types.
----I agree, ints shouldn't be mixed with rationals. But floats
could. This argument is the main reason why I said most people
compared rational with integers. Many operations that requires ints
and don't accept rationals also don't accept floats.

Other arguments:
- Slow: Doing addition and subtraction in fractions sure is expensive,
but doing division (the heaviest arithmetic operation) is extremely
fast in fractional numbers compared to in floating numbers. It is
clear that doing two integer multiplication and switching numerator-
denominator is much faster than doing a single float division.
- Memory Intensive: To represent 1/3 to infinite accuracy requires two-
integer-space (theoretically, 2 bytes). There are some numbers that
are hard to represent in fractions, yes, but in general those numbers
could be represented using two-long-space (variable-width longs). And
whenever accuracy isn't that important, it could be possible to create
a method that would lossily approximate the current fraction to an
acceptable length. Anyway, most computers nowadays is packed with
gigantic memory, why bother with such a small issue.
- Rationals must present themselves as decimal floats or it'll be
confusing: There will be no confusion in a good written code.
Progammers that writes good code would always use the 'behind-the-
scene' number, they wouldn't convert a previously 'string'ed number
back into calculation. And a convention can be created to represent a
fraction in a single line output (like * for multiplication, / for
division, they don't exist in paper maths) that would completely
eliminate any confusion of the user (well informed about the
convention, most people that never used computer before often tried to
use x and : to represent mult and div), even when the fractional
number is outputted to the foreground UI.

Dec 15 '07 #1
18 1746
On Dec 15, 2:00 pm, Lie <Lie.1...@gmail.comwrote:
I'm very surprised actually, to see that Python rejected the use of
fractional/rational numbers. However, when I read the PEP, I know
exactly why the proposal was rejected: People compared fractions with
integers, while it should be more fairly compared to floats.
Pretty lame reasoning, isn't it?

I use the rationals from the gmpy module very
successfully.

All these arguments that follow are just silly.
>
Arguments against:
- When I use the result of / as a sequence index, it's usually an
error which should not be hidden by making the program working for
some data, since it will break for other data.
----In Python 3 (and 2 w/ __future__), the / operator would always
return floats, and floats is invalid as sequence index, even if the
value of the float is whole. Since fractions is created with the /
operator on two integers, the behavior of fractions should mimics
float. So putting fractional type as sequence index should always be
considered as error (exception), a behavior consistent with floats.
Thus, the arguments specified above has turned invalid, at least in
Python 3.
- (this assumes the same type for them:) Int is a good type in itself,
not to be mixed with rationals. The fact that something is an integer
should be expressible as a statement about its type. Many operations
require ints and don't accept rationals. It's natural to think about
them as about different types.
----I agree, ints shouldn't be mixed with rationals. But floats
could. This argument is the main reason why I said most people
compared rational with integers. Many operations that requires ints
and don't accept rationals also don't accept floats.

Other arguments:
- Slow: Doing addition and subtraction in fractions sure is expensive,
but doing division (the heaviest arithmetic operation) is extremely
fast in fractional numbers compared to in floating numbers. It is
clear that doing two integer multiplication and switching numerator-
denominator is much faster than doing a single float division.
- Memory Intensive: To represent 1/3 to infinite accuracy requires two-
integer-space (theoretically, 2 bytes). There are some numbers that
are hard to represent in fractions, yes, but in general those numbers
could be represented using two-long-space (variable-width longs). And
whenever accuracy isn't that important, it could be possible to create
a method that would lossily approximate the current fraction to an
acceptable length. Anyway, most computers nowadays is packed with
gigantic memory, why bother with such a small issue.
- Rationals must present themselves as decimal floats or it'll be
confusing: There will be no confusion in a good written code.
Progammers that writes good code would always use the 'behind-the-
scene' number, they wouldn't convert a previously 'string'ed number
back into calculation. And a convention can be created to represent a
fraction in a single line output (like * for multiplication, / for
division, they don't exist in paper maths) that would completely
eliminate any confusion of the user (well informed about the
convention, most people that never used computer before often tried to
use x and : to represent mult and div), even when the fractional
number is outputted to the foreground UI.
Dec 15 '07 #2
Lie
<cont.>
The easiest implementation of using fractional datatype is probably to
add a new operator. Some scientific calculators provide a special
operator to signify a fraction (somewhat on the shape of a small L in
mine) and I strongly believe that their internal calculation probably
used fractions even when regular division is used, only when the
calculator have difficulties using fraction (like calculating sin/cos/
tan function) or the screen is not wide enough to represent the
fraction would it use regular division.

Python implemented complex numbers, why not fractions?

Random ramble past here:
Actually, my vision would be not only fractions, but also rooted
number (square root, cube root, etc), it could be possible to
implement a type where a number consist of a rooted number times a
multiplier plus a variable [a + b * root(c, d)]. But I guess this
would be extremely complex and it requires nesting, probably very slow
if implementation isn't good. The advantage of using such is much
faster operations, as long as str() is not called. This actually
reflects my way of doing paper math, I save the lossy operations
(float division, root, trigonometric function) until the very end of
calculation (I'm not fundamentalist though, so compromise sometimes is
done here and there).
Dec 15 '07 #3
On Dec 15, 2007 10:05 PM, Lie <Li******@gmail.comwrote:
Random ramble past here:
Actually, my vision would be not only fractions, but also rooted
number (square root, cube root, etc), it could be possible to
implement a type where a number consist of a rooted number times a
multiplier plus a variable [a + b * root(c, d)]. But I guess this
would be extremely complex and it requires nesting, probably very slow
if implementation isn't good. The advantage of using such is much
faster operations, as long as str() is not called. This actually
reflects my way of doing paper math, I save the lossy operations
(float division, root, trigonometric function) until the very end of
calculation (I'm not fundamentalist though, so compromise sometimes is
done here and there).
You're looking for a computer algebra system. Try sympy:
http://code.google.com/p/sympy/

Fredrik
Dec 15 '07 #4
Lie
On Dec 16, 4:55 am, "Fredrik Johansson" <fredrik.johans...@gmail.com>
wrote:
On Dec 15, 2007 10:05 PM, Lie <Lie.1...@gmail.comwrote:
Random ramble past here:
Actually, my vision would be not only fractions, but also rooted
number (square root, cube root, etc), it could be possible to
implement a type where a number consist of a rooted number times a
multiplier plus a variable [a + b * root(c, d)]. But I guess this
would be extremely complex and it requires nesting, probably very slow
if implementation isn't good. The advantage of using such is much
faster operations, as long as str() is not called. This actually
reflects my way of doing paper math, I save the lossy operations
(float division, root, trigonometric function) until the very end of
calculation (I'm not fundamentalist though, so compromise sometimes is
done here and there).

You're looking for a computer algebra system. Try sympy:http://code.google.com/p/sympy/

Fredrik
Yeah, that's why I consider them too complex for being included as a
core of a general programming language like Python. Nevertheless,
fraction datatype _IS_ elementary enough to be included as core
language feature.
Dec 15 '07 #5
I think the main objection to rationals is that extensive
computation with them tends to result in numbers requiring
larger and larger amounts of storage. I believe that ABC
made routine use of rationals, and this caused programs
to get bogged down for no apparent reason, as rationals
were being used behind the scenes when people didn't
realise it.

So while rationals might be useful to have available for
some things, you should have to explicitly ask for them.
Returning rationals from '/' applied to integers would
be a bad idea, for example.

--
Greg
Dec 16 '07 #6
On Dec 15, 6:52 pm, greg <g...@cosc.canterbury.ac.nzwrote:
So while rationals might be useful to have available for
some things, you should have to explicitly ask for them.
Returning rationals from '/' applied to integers would
be a bad idea, for example.
From my reading of the PEP, it doesn't suggest such automatic
coercions (neither rejects them explicitly though). Given the huge
discussions about integer vs true division, it would be very
controversial to suggest implicit rational division.

Regardless, a builtin (or at least standard library) rational type
would be nice to have. Of course folks that *really need* rationals
are already using some 3rd party library, but for the rest of us it
would be an improvement in several cases where currently floats are
used, just like the motivation for Decimals. Only difference seems to
be that there aren't so many or compelling use cases for rationals as
for decimals (mainly money counting).

George
Dec 16 '07 #7
On Sat, 15 Dec 2007 22:20:22 -0800, Dennis Lee Bieber wrote:
On Sun, 16 Dec 2007 06:09:06 -0000, Steven D'Aprano
<st***@REMOVE-THIS-cybersource.com.audeclaimed the following in
comp.lang.python:
>Yes, but my point (badly put, I admit) was that people find fractions
far easier to work with than they find floating point numbers. And with
any rational data type worth the name, you simply should never get
anything as unintuitive as this:
>>from __future__ import division
4/10 + 2/10 == 6/10
False

Which only seems to me to prove that having integer division return
a floating value is a mistake <G>
What integer division? It's floating point division. The / operator
creates floats. If I wanted integer division, I would have used //.

My background with mostly ancient
languages (FORTRAN) reads that and sees "0 + 0 == 0",
With some floating point implementations, one can find values such that
x == 0.0 and y == 0.0 but x + y != 0.0.
and "4.0/10.0 + 2.0/10.0 == 6.0/10.0" automatically makes me leery...
*shrug*

That's the whole point. Floating point math is weird. Rationals are not.
Using floats when you actually need rationals is dangerous.
--
Steven
Dec 16 '07 #8
In article <41**********************************@s12g2000prg. googlegroups.com>,
George Sakkis <ge***********@gmail.comwrote:
>
Regardless, a builtin (or at least standard library) rational type
would be nice to have. Of course folks that *really need* rationals
are already using some 3rd party library, but for the rest of us it
would be an improvement in several cases where currently floats are
used, just like the motivation for Decimals. Only difference seems to
be that there aren't so many or compelling use cases for rationals as
for decimals (mainly money counting).
You've precisely hit on the problem: previous discussion about rationals
has bogged down because proponents insisted on making it a built-in type
rather than a library. If a PEP were submitted with code for a library,
there would be little trouble getting it accepted -- just like Decimal.

Even now, after a couple of releases with Decimal in the library, there
remains much opposition to a Decimal built-in, not even talking about
Decimal literals.
--
Aahz (aa**@pythoncraft.com) <* http://www.pythoncraft.com/

"Typing is cheap. Thinking is expensive." --Roy Smith
Dec 16 '07 #9
Mel
Steven D'Aprano wrote:
Yes, but my point (badly put, I admit) was that people find fractions far
easier to work with than they find floating point numbers.
I'm not so sure. I got caught by the comic XKCD's
infinite-resistor-grid thing, and simplified it to a ladder network --
call it L -- made up of 2 1-ohm resistors in series with a 1-ohm
resistor paralleled by L. Simulating this -- assuming an arbitrary
endpoint with resistance 3 -- well, it takes a little thought to
decide that 11/15 < 3/4, and a lot more to decide the same thing for
153/209 and thus decide whether the series is coming or going.

Then when you work out the right answer from

L = 2 + (L / (L+1))

that answer depends on sqrt(12), which Rationals handle just as badly
as floats, and at far greater expense.

I wrote a Rational class back when I was learning to do these things
in Python, and it was actually pretty easy: a dash of GCD, a pinch of
partial fractions, and a lot of following the Python Reference Manual.
It eventually worked as advertised, but I haven't used it since.
It could stand to be updated to use the __new__ method and produce
genuinely immutable instances, if I could find the source.

Mel.
And with any
rational data type worth the name, you simply should never get anything
as unintuitive as this:
>>>from __future__ import division
4/10 + 2/10 == 6/10
False
Dec 16 '07 #10
On 16 dic, 06:40, Lie <Lie.1...@gmail.comwrote:
[btw, off topic, in music, isn't 1/4 and 2/8 different? I'm not very
keen of music though, so correct me if I'm wrong.]
As a time signature 1/4 has no sense, but 3/4 and 6/8 are different
things. In the standard musical notation both numbers are written one
above the other, and no "division" line is used. Note that they just
*look* like a fraction when written in text form, like here, because
it's not easy to write one above the other.
3/4 is read as "three by four", not "three quarters" -at least in my
country- so there is even less confussion.

--
Gabriel Genellina
Dec 17 '07 #11
Gabriel Genellina wrote:
On 16 dic, 06:40, Lie <Lie.1...@gmail.comwrote:
>[btw, off topic, in music, isn't 1/4 and 2/8 different? I'm not very
keen of music though, so correct me if I'm wrong.]
As a time signature 1/4 has no sense
Actually, I'm playing a show right now that has a one beat vamp. It's a
single repeated measure in 1/4 time.

To addres the real point, though, I don't think of a time signature as a
rational number, although it correctly reflects what portion of a whole
note can be found within a measure. I consider it to have two separate
pieces of information: the length of the beat and the number of those
beats per bar. When I've written code to represent music I have used
rationals to represent when something occurs, but a different structure
to represent time signatures.

--
Brian

Dec 17 '07 #12
Since the US, at least, uses whole/half/quarter/eighth/sixteenth...
notes, three-quarter and six-eight time falls out...
I don't think this is technically true, but I've never been able to
tell the difference.
Dec 17 '07 #13
On 2007-12-17, Gabriel Genellina <ga*******@yahoo.com.arwrote:
On 16 dic, 06:40, Lie <Lie.1...@gmail.comwrote:
>[btw, off topic, in music, isn't 1/4 and 2/8 different? I'm not very
keen of music though, so correct me if I'm wrong.]

As a time signature 1/4 has no sense, but 3/4 and 6/8 are
different things. In the standard musical notation both numbers
are written one above the other, and no "division" line is
used. Note that they just *look* like a fraction when written
in text form, like here, because it's not easy to write one
above the other. 3/4 is read as "three by four", not "three
quarters" -at least in my country- so there is even less
confussion.
Time signatures are crap. They should have switched to a number
over a note value a long time ago; we could have easily avoided
abominable travesties like the time signature on the 2nd
movement of Beethoven's 9th (B needed four over dotted quarter). If
music notation had been invented by a computer scientist we
wouldn't be stuck in the current mess in which 6/8 means two
completely different meters (3 over quarter, or 2 over dotted
quarter).

And... er... Python doesn't need a time signature data type. But
rationals would be quite nifty. ;-)

--
Neil Cerutti
Dec 17 '07 #14

"Dan Upton" <up***@virginia.eduwrote in message
news:55******************************************@ mail.gmail.com...
| Since the US, at least, uses
whole/half/quarter/eighth/sixteenth...
| notes, three-quarter and six-eight time falls out...
|
| I don't think this is technically true, but I've never been able to
| tell the difference.

I learned three-four, four-four, six-eight, etc. as time sigs. Not a
fraction.

Dec 17 '07 #15
On Dec 16, 2007 10:32 PM, Terry Reedy <tj*****@udel.eduwrote:
>
"Dan Upton" <up***@virginia.eduwrote in message
news:55******************************************@ mail.gmail.com...

| Since the US, at least, uses
whole/half/quarter/eighth/sixteenth...
| notes, three-quarter and six-eight time falls out...
|
| I don't think this is technically true, but I've never been able to
| tell the difference.

I learned three-four, four-four, six-eight, etc. as time sigs. Not a
fraction.
I can't tell whether you're agreeing with me or not...

At any rate though, if time signatures really fell out as reducible
fractions, then why don't we just reduce 4/4 to 1 and call the whole
thing off? ;)
Dec 17 '07 #16

"Dan Upton" <up***@virginia.eduwrote in message
news:55*****************************************@m ail.gmail.com...

| | notes, three-quarter and six-eight time falls out...
| |
| | I don't think this is technically true, but I've never been able to
| | tell the difference.
| >
| I learned three-four, four-four, six-eight, etc. as time sigs. Not a
| fraction.
| >
|
| I can't tell whether you're agreeing with me or not...

I disagreed with three-quarter rather than three-four and agreed with
six-eight.

Dec 17 '07 #17
En Mon, 17 Dec 2007 10:35:39 -0300, Neil Cerutti <ho*****@yahoo.com>
escribió:
On 2007-12-17, Gabriel Genellina <ga*******@yahoo.com.arwrote:
>On 16 dic, 06:40, Lie <Lie.1...@gmail.comwrote:
>>[btw, off topic, in music, isn't 1/4 and 2/8 different? I'm not very
keen of music though, so correct me if I'm wrong.]

As a time signature 1/4 has no sense, but 3/4 and 6/8 are
different things. In the standard musical notation both numbers
are written one above the other, and no "division" line is
used. Note that they just *look* like a fraction when written
in text form, like here, because it's not easy to write one
above the other. 3/4 is read as "three by four", not "three
quarters" -at least in my country- so there is even less
confussion.

Time signatures are crap. They should have switched to a number
over a note value a long time ago; we could have easily avoided
abominable travesties like the time signature on the 2nd
movement of Beethoven's 9th (B needed four over dotted quarter). If
music notation had been invented by a computer scientist we
wouldn't be stuck in the current mess in which 6/8 means two
completely different meters (3 over quarter, or 2 over dotted
quarter).
That was proposed by (some great musician from XIX century that I can't
remember) but it's hard to change habits.
The idea was to use: above, number of beats, and below, the note lasting
one beat, *always*. So conventional 6/8 would be 2/"dotted quarter" with a
dotted quarted drawn as itself, not implied by a number. This allows for
more meaningful signatures, like 3+3+2/"eight note" for some Piazzolla
tangos that are now written as 4/4 (but don't have the stress pattern for
4/4 at all).
And... er... Python doesn't need a time signature data type. But
rationals would be quite nifty. ;-)
I'm happy enough with rationals as 3rd party library (like gmpy)

--
Gabriel Genellina

Dec 18 '07 #18
Time signatures are crap. They should have switched to a number
over a note value a long time ago; we could have easily avoided
abominable travesties like the time signature on the 2nd
movement of Beethoven's 9th (B needed four over dotted quarter). If
music notation had been invented by a computer scientist we
wouldn't be stuck in the current mess in which 6/8 means two
completely different meters (3 over quarter, or 2 over dotted
quarter).

That was proposed by (some great musician from XIX century that I can't
remember) but it's hard to change habits.
The idea was to use: above, number of beats, and below, the note lasting
one beat, *always*. So conventional 6/8 would be 2/"dotted quarter" with a
dotted quarted drawn as itself, not implied by a number. This allows for
more meaningful signatures, like 3+3+2/"eight note" for some Piazzolla
tangos that are now written as 4/4 (but don't have the stress pattern for
4/4 at all).
Hi! While I wouldn't agree without reservation that time sigs are crap
(more like they're making the best of a bad situation) I do agree that
number over note value is way better. In fact, the college I teach at
starts with time signatures that way (based on Kodaly): 2 over quarter
note, 2 over dotted quarter etc. It's amazing how well everybody
understands until we switch to 6/8. Then everything falls apart,
because it's no longer intuitive.

cheers
dafydd

--
www.sideshowmedia.ca
skype: chickeninthegrass
Dec 18 '07 #19

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

21 posts views Thread by Mike Meyer | last post: by
20 posts views Thread by Mike Meyer | last post: by
3 posts views Thread by Schüle Daniel | last post: by
1 post views Thread by ben kipkorir | last post: by
135 posts views Thread by robinsiebler | last post: by
38 posts views Thread by Bill Cunningham | last post: by
5 posts views Thread by anumliaqat | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.