Re: [Tutor] Fraction - differing interpretations for number and string - presentation

2015-04-17 Thread Oscar Benjamin
On 17 April 2015 at 03:29, Steven D'Aprano  wrote:
> On Thu, Apr 16, 2015 at 03:11:59PM -0700, Jim Mooney wrote:
>
>> So the longer numerator and denominator would, indeed, be more accurate if
>> used in certain calculations rather than being normalized to a float - such
>> as in a Fortran subroutine or perhaps if exported to a machine with a
>> longer bit-length? That's mainly what I was interested in - if there is any
>> usable difference between the two results.

If it's okay to use float and then go onto machines with higher/lower
precision then the extra precision must be unnecessary in which case
why bother with the Fraction type? If you really need to transfer your
float from one program/machine to another then why not just send the
decimal representation. Your 64-bit float should be able to round-trip
to decimal text and back for any IEEE-754 compliant systems. Writing
it as a fraction doesn't gain any extra accuracy. (BTW Python the
language guarantees that float is always an IEEE-754 64-bit float on
any machine).

When you use floats the idea is that you're using fixed-width floating
point as an approximation of real numbers. You're expected to know
that there will be some rounding and not consider your computation to
be exact. So the difference between 1.64 and the nearest IEEE-754
64-bit binary float should be considered small enough not to worry
about.

It's possible that in your calculations you will also be using
functions from the math module such as sin, cos, etc. and these
functions cannot be computed *exactly* for an input such as 1.64.
However they can be computed up to any desired finite precision so we
can always get the nearest possible float which is what the math
module will do.

When you use the fractions module and the Fraction type the idea is
that floating point inexactness is unacceptable to you. You want to
perform *exact* arithmetic and convert from other numeric types or
text exactly. You won't be able to use functions like sin and cos but
that's no loss since you wouldn't be able to get an exact rational
result there anyway.

Because the Fractions module is designed for the "I want everything to
be exact" use case conversion from float to Fraction is performed
exactly. Conversion from string or Decimal to Fraction is also exact.
The Fraction will also display its exact value when printed and that's
what you're seeing.

If you really want higher accuracy than float consider ditching it
altogether in favour of Fraction which will compute everything you
want exactly. However there's no point in doing this if you're also
mixing floats into the calculations. float+Fraction coerces to float
discarding accuracy and then calculates with floating point rounding.
If that's acceptable then don't bother with Fraction in the first
place. If not make sure you stick to only using Fraction.

> You're asking simple questions that have complicated answers which
> probably won't be what you are looking for. But let's try :-)
>
> Let's calculate a number. The details don't matter:
>
> x = some_calculation(a, b)
> print(x)
>
> which prints 1.64. Great, we have a number that is the closest possible
> base 2 float to the decimal 164/100. If we convert that float to a
> fraction *exactly*, we get:
>
> py> Fraction(1.64)
> Fraction(738590337613, 4503599627370496)
>
> So the binary float which displays as 1.64 is *actually* equal to
> 738590337613/4503599627370496, which is just a tiny bit less than
> the decimal 1.64:
>
> py> Fraction(1.64) - Fraction("1.64")
> Fraction(-11, 112589990684262400)
>
> That's pretty close. The decimal value that normally displays as 1.64 is
> perhaps more accurately displayed as:
>
> py> "%.23f" % 1.64
> '1.63990230037'
>
> but even that is not exact.

Just to add to Steven's point. The easiest way to see the exact value
of a float in decimal format is:
>>> import decimal
>>> decimal.Decimal(1.64)
Decimal('1.6399023003738329862244427204132080078125')

> The reality is that very often, the difference
> isn't that important. The difference between
>
> 1.64 inches
>
> and
>
> 1.63990230037 inches
>
> is probably not going to matter, especially if you are cutting the
> timber with a chainsaw.

I once had a job surveying a building site as an engineer's assistant.
I'd be holding a reflector stick while he operated the laser sight
machine (EDM) from some distance away and spoke to me over the radio.
He'd say "mark it 10mm to the left". The marker spray would make a
circle that was about 100mm in diameter. Then I would get 4 unevenly
shaped stones (that happened to be lying around) and drop them on the
ground to mark out the corners of a 1500mm rectangle by eye.
Afterwards the excavator would dig a hole there using a bucket that
was about 1000mm wide. While digging the stones would get moved around
and the operator would end up just vaguely guessing where the original
marks had been.

The engineer was absolutely insistent that it h

Re: [Tutor] Fraction - differing interpretations for number and string - presentation

2015-04-16 Thread Steven D'Aprano
On Thu, Apr 16, 2015 at 03:11:59PM -0700, Jim Mooney wrote:

> So the longer numerator and denominator would, indeed, be more accurate if
> used in certain calculations rather than being normalized to a float - such
> as in a Fortran subroutine or perhaps if exported to a machine with a
> longer bit-length? That's mainly what I was interested in - if there is any
> usable difference between the two results.

You're asking simple questions that have complicated answers which 
probably won't be what you are looking for. But let's try :-)

Let's calculate a number. The details don't matter:

x = some_calculation(a, b)
print(x)

which prints 1.64. Great, we have a number that is the closest possible 
base 2 float to the decimal 164/100. If we convert that float to a 
fraction *exactly*, we get:

py> Fraction(1.64)
Fraction(738590337613, 4503599627370496)

So the binary float which displays as 1.64 is *actually* equal to 
738590337613/4503599627370496, which is just a tiny bit less than 
the decimal 1.64:

py> Fraction(1.64) - Fraction("1.64")
Fraction(-11, 112589990684262400)

That's pretty close. The decimal value that normally displays as 1.64 is 
perhaps more accurately displayed as:

py> "%.23f" % 1.64
'1.63990230037'

but even that is not exact.

So which is the "right" answer? That depends.

(1) It could be that our initial calculation some_calculation(a, b) 
actually was 164/100, say, in which case the *correct* result should be 
decimal 1.64 = Fraction("1.64") and the 7385blahblahblah/blahblahblah is 
just an artifact of the fact that floats are binary.

(2) Or it could be that the some_calculation(a, b) result actually was
738590337613/4503599627370496, say, in which case it is a mere 
coincidence that this number displays as 1.64 when treated as a binary 
float. The long 7385blahblahblah numerator and denominator is exactly 
correct, and decimal 1.64 is a approximation.

There is no way of telling in advance which interpretation is correct. 
You need to think about the calculation you performed and decide what it 
means, not just look at the final result.

Although... 9 times out of 10, if you get something *close* to an exact 
decimal, a coincidence is not likely. If you get exactly 0.5 out of a 
calculation, rather than 0.50001, then it probably should be 
exactly 1/2. *Probably*. The reality is that very often, the difference 
isn't that important. The difference between

1.64 inches

and

1.63990230037 inches

is probably not going to matter, especially if you are cutting the 
timber with a chainsaw.



-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Fraction - differing interpretations for number and string - presentation

2015-04-16 Thread Jim Mooney
 The whole point of the discussion is that this is *not* a presentation
issue. Fraction(1.64) and Fraction("1.64") *are* two different numbers
because one gets constructed from a value that is not quite 1.64.

Wolfgang Maier
--
So the longer numerator and denominator would, indeed, be more accurate if
used in certain calculations rather than being normalized to a float - such
as in a Fortran subroutine or perhaps if exported to a machine with a
longer bit-length? That's mainly what I was interested in - if there is any
usable difference between the two results.

Jim

The Paleo diet causes Albinism
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Fraction - differing interpretations for number and string - presentation

2015-04-16 Thread Dave Angel

On 04/16/2015 01:24 PM, Jim Mooney wrote:


Is this "inaccurate"? Well, in the sense that it is not the exact true
mathematical result, yes it is, but that term can be misleading if you
think of it as "a mistake". In another sense, it's not inaccurate, it is
as accurate as possible (given the limitation of only having a certain
fixed number of bits).
--
Steve



---
Understood about the quondam inexactness of floating point bit
representation. I was just wondering why the different implementation of
representing it when using Fraction(float) as opposed to using
Fraction(string(float)).


You didn't use str(float), you used a simple str.  So there was no 
quantization error since it was never converted to binary floating 
point.  If you have a number that happens to be an exact decimal number, 
don't convert it via float().  Either convert it via Decimal() or 
convert it directly to fraction.



  In terms of user presentation, the string usage

has smaller numbers for the ratio, so it would be more understandable and
should, I assume, be chosen for GUI display.



Presumably you didn't read my message.  When you use a literal 1.64 in 
your code, you're telling the compiler to call the float() function on 
the token.  You've already forced the quantization error.  Nothing to do 
with the fraction class.


--
DaveA
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Fraction - differing interpretations for number and string - presentation

2015-04-16 Thread Danny Yoo
On Apr 16, 2015 1:42 PM, "Jim Mooney"  wrote:

> Understood about the quondam inexactness of floating point bit
> representation. I was just wondering why the different implementation of
> representing it when using Fraction(float) as opposed to using
> Fraction(string(float)).

Ah.  Correction.  You want to say: .. using Fraction(float) as opposed to
using
Fraction(**string**).
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Fraction - differing interpretations for number and string - presentation

2015-04-16 Thread Wolfgang Maier

On 16.04.2015 19:24, Jim Mooney wrote:


Understood about the quondam inexactness of floating point bit
representation. I was just wondering why the different implementation of
representing it when using Fraction(float) as opposed to using
Fraction(string(float)).  In terms of user presentation, the string usage
has smaller numbers for the ratio, so it would be more understandable and
should, I assume, be chosen for GUI display.



The whole point of the discussion is that this is *not* a presentation 
issue. Fraction(1.64) and Fraction("1.64") *are* two different numbers 
because one gets constructed from a value that is not quite 1.64.

What sense would it make for Fraction(1.64) to represent itself inexactly ?
However, if you really want a shortened, but inexact answer: Fractions 
have a limit_denominator method that you could use like so:


>>> Fraction(1.64).limit_denominator(25)
Fraction(41, 25)


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Fraction - differing interpretations for number and string - presentation

2015-04-16 Thread Jim Mooney
>
> Is this "inaccurate"? Well, in the sense that it is not the exact true
> mathematical result, yes it is, but that term can be misleading if you
> think of it as "a mistake". In another sense, it's not inaccurate, it is
> as accurate as possible (given the limitation of only having a certain
> fixed number of bits).
> --
> Steve
>

---
Understood about the quondam inexactness of floating point bit
representation. I was just wondering why the different implementation of
representing it when using Fraction(float) as opposed to using
Fraction(string(float)).  In terms of user presentation, the string usage
has smaller numbers for the ratio, so it would be more understandable and
should, I assume, be chosen for GUI display.
-- 
Jim

The Paleo diet causes Albinism
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor