Re: [Tutor] Removing duplicates

2018-08-02 Thread Oscar Benjamin
On 2 August 2018 at 13:49, Peter Otten <__pete...@web.de> wrote:
> Oscar Benjamin wrote:
>>
>> Comparing floats for equality can be flakey. Sometimes two floats that
>> should be equal will not compare equal e.g.:
>>
> 0.01 + 0.1 - 0.1 == 0.01
>> False
>
> Do you know if there's a way to construct an example where
>
> i/k != (n*i)/(n*k)
>
> with preferrably small integers i, k, and n?

There wouldn't be for small integers. The simplest possible way for
Python to implement the division is to convert both numerator and
denominator to float before dividing with floating point. For integers
up to ~10**16 the conversion to float will be exact. IEEE 754 requires
that the divisions would always give the same result since it should
give the true result correctly rounded: both divisions should give the
same result if the true ratio of the floats is the same.

Actually looking here:
https://github.com/python/cpython/blob/3.7/Objects/longobject.c#L3835
that is exactly what happens for small integers. Also it looks as if
the algorithm for large integers is designed to compute the true
result correctly rounded as well.

As it mentions in the code though "results may be subject to double
rounding on x86 machines that operate with
the x87 FPU set to 64-bit precision." What that means is that on some
32 bit CPUs that don't have SSE2 you may see results that are rounded
differently.

So leaving aside older hardware I don't think there will be a case
where i/k != (n*i)/(n*k). All the same I prefer not to use floating
point for exact calculations and I would always recommend that a
beginner think of floating point operations as inexact.

> Python's integer division
> algorithm defeats my naive attempts ;)

I haven't tried to properly understand the code in long_true_divide
but it definitely looks like whoever wrote it knew what they were
doing :)

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


Re: [Tutor] Removing duplicates

2018-08-02 Thread Peter Otten
Oscar Benjamin wrote:

> On 1 August 2018 at 21:38, Roger Lea Scherer  wrote:
>>
>> I'm trying to get a list of tuples to be a float, a numerator, and a
>> denominator for all the fractions: halves, thirds, fourths etc up to
>> ninths. 1/2 returns the same float as 2/4, 3/6, 4/8. I would like to keep
>> only the 1/2. When I try (line 18) to "pop"  from the list I get a
>> "TypeError:
>> integer argument expected, got float". When I try (line 18)  to "remove"
>> from the list, nothing happens: nothing is removed and I do not receive
>> an error message.
>>
>> What do you think is a good way to solve this?
>>
>> Thank you as always.
>>
>> import math
>>
>> fractions = [(0, 0, 0)]
>>
>> for i in range(1, 10):
>> for j in range(1, 10):
>> if i < j:
>> x = i/j
>> if x not in fractions:
>> fractions.append((x, i, j))
>> sortedFrac =  sorted(fractions)
>>
>> print(sortedFrac)
>>
>> for i in range(len(sortedFrac)):
>> try:
>> if sortedFrac[i][0] == sortedFrac[i-1][0]: # so if the float
>> equals
>> the previous float
>> sortedFrac.pop(sortedFrac[i][0])   # remove the
>> second
>> float
>> else:
>> sortedFrac.append(sortedFrac[i][0])
>> except ValueError:
>> continue
> 
> Comparing floats for equality can be flakey. Sometimes two floats that
> should be equal will not compare equal e.g.:
> 
 0.01 + 0.1 - 0.1 == 0.01
> False

Do you know if there's a way to construct an example where

i/k != (n*i)/(n*k)

with preferrably small integers i, k, and n? Python's integer division 
algorithm defeats my naive attempts ;)

I had to resort to i/k == i/(k + 1)

>>> k = 10**18
>>> 1/k == 1/(k+1)
True

> This happens in this case because of intermediate rounding errors. I
> don't think that should affect you since you are doing precisely one
> floating point operation i/j to calculate each of your floats but
> unless you have a very solid understanding of binary floating point I
> would recommend that you shouldn't compare floating point values as in
> a==b.
> 
> For this particular problem I would use integer arithmetic or I would
> use the fractions module. Doing this with integers you should
> normalise the numerator and denominator by dividing out their GCD. The
> fractions module takes care of this for you internally.
> https://docs.python.org/3.7/library/fractions.html
> 
> Otherwise in general to remove duplicates you would be better of with
> a set rather than a list. If you only put x in the set and not i and j
> then the set will automatically take care of duplicates:
> https://docs.python.org/3.7/tutorial/datastructures.html#sets

And if you want to keep i and j you can use a dict:

fractions = {}
for i in range(1, 10):
for j in range(1, 10):
if i < j:
x = i/j
if x not in fractions:
fractions[x] = x, i, j
sorted_unique_fractions =  sorted(fractions.values())

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


Re: [Tutor] Removing duplicates

2018-08-02 Thread Oscar Benjamin
On 1 August 2018 at 21:38, Roger Lea Scherer  wrote:
>
> I'm trying to get a list of tuples to be a float, a numerator, and a
> denominator for all the fractions: halves, thirds, fourths etc up to
> ninths. 1/2 returns the same float as 2/4, 3/6, 4/8. I would like to keep
> only the 1/2. When I try (line 18) to "pop"  from the list I get a "TypeError:
> integer argument expected, got float". When I try (line 18)  to "remove"
> from the list, nothing happens: nothing is removed and I do not receive an
> error message.
>
> What do you think is a good way to solve this?
>
> Thank you as always.
>
> import math
>
> fractions = [(0, 0, 0)]
>
> for i in range(1, 10):
> for j in range(1, 10):
> if i < j:
> x = i/j
> if x not in fractions:
> fractions.append((x, i, j))
> sortedFrac =  sorted(fractions)
>
> print(sortedFrac)
>
> for i in range(len(sortedFrac)):
> try:
> if sortedFrac[i][0] == sortedFrac[i-1][0]: # so if the float equals
> the previous float
> sortedFrac.pop(sortedFrac[i][0])   # remove the second
> float
> else:
> sortedFrac.append(sortedFrac[i][0])
> except ValueError:
> continue

Comparing floats for equality can be flakey. Sometimes two floats that
should be equal will not compare equal e.g.:

>>> 0.01 + 0.1 - 0.1 == 0.01
False

This happens in this case because of intermediate rounding errors. I
don't think that should affect you since you are doing precisely one
floating point operation i/j to calculate each of your floats but
unless you have a very solid understanding of binary floating point I
would recommend that you shouldn't compare floating point values as in
a==b.

For this particular problem I would use integer arithmetic or I would
use the fractions module. Doing this with integers you should
normalise the numerator and denominator by dividing out their GCD. The
fractions module takes care of this for you internally.
https://docs.python.org/3.7/library/fractions.html

Otherwise in general to remove duplicates you would be better of with
a set rather than a list. If you only put x in the set and not i and j
then the set will automatically take care of duplicates:
https://docs.python.org/3.7/tutorial/datastructures.html#sets

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


[Tutor] Removing duplicates

2018-08-02 Thread Roger Lea Scherer
I'm trying to get a list of tuples to be a float, a numerator, and a
denominator for all the fractions: halves, thirds, fourths etc up to
ninths. 1/2 returns the same float as 2/4, 3/6, 4/8. I would like to keep
only the 1/2. When I try (line 18) to "pop"  from the list I get a "TypeError:
integer argument expected, got float". When I try (line 18)  to "remove"
from the list, nothing happens: nothing is removed and I do not receive an
error message.

What do you think is a good way to solve this?

Thank you as always.

import math

fractions = [(0, 0, 0)]

for i in range(1, 10):
for j in range(1, 10):
if i < j:
x = i/j
if x not in fractions:
fractions.append((x, i, j))
sortedFrac =  sorted(fractions)

print(sortedFrac)

for i in range(len(sortedFrac)):
try:
if sortedFrac[i][0] == sortedFrac[i-1][0]: # so if the float equals
the previous float
sortedFrac.pop(sortedFrac[i][0])   # remove the second
float
else:
sortedFrac.append(sortedFrac[i][0])
except ValueError:
continue


-- 
Roger Lea Scherer
623.255.7719

  *Strengths:*
   Input, Strategic,
Responsibility,

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


[Tutor] Removing duplicates in a list with a fixed length of items in the list.

2007-01-11 Thread Adam Cripps
I have a list which comprises of simple random arithmetic problems for
teachers to give to their pupils. This list must be a set length (if
the teacher asks for 10 questions, they should get 10 questions), but
should not have any duplicates.

I've seen the use of sets, but this reduces the size of the list, when
I have to have a fixed length.

Is there a quick way of checking if a string is already within a list
without iterating over the items of the list (which will slow the
application down slightly)?

TIA
Adam
-- 
http://www.monkeez.org
PGP key: 0x7111B833
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Removing duplicates in a list with a fixed length of items in the list.

2007-01-11 Thread Kent Johnson
Adam Cripps wrote:
 I have a list which comprises of simple random arithmetic problems for
 teachers to give to their pupils. This list must be a set length (if
 the teacher asks for 10 questions, they should get 10 questions), but
 should not have any duplicates.
 
 I've seen the use of sets, but this reduces the size of the list, when
 I have to have a fixed length.
 
 Is there a quick way of checking if a string is already within a list
 without iterating over the items of the list (which will slow the
 application down slightly)?

Hmm. If you are trying to pick 10 elements at random from a larger list, 
use random.sample(problems, 10)

If for some reason that doesn't work for you (maybe you are creating 
problems on the fly?) you could build a set in a loop, adding items 
until it is the size you want:
problemSet = set()
while len(problemSet)  10:
   # do something to add a (possibly) new problem to the set

Finally, unless your lists are huge (thousands of items, at a guess) or 
you are doing this very many times (thousands of times), you will not 
notice the time it takes to search the list for duplicates.

Kent

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Removing duplicates in a list with a fixed length of items in the list.

2007-01-11 Thread Adam Cripps
On 1/11/07, Adam Cripps [EMAIL PROTECTED] wrote:
 On 1/11/07, Kent Johnson [EMAIL PROTECTED] wrote:
  Adam Cripps wrote:
   I have a list which comprises of simple random arithmetic problems for
   teachers to give to their pupils. This list must be a set length (if
   the teacher asks for 10 questions, they should get 10 questions), but
   should not have any duplicates.
  
   I've seen the use of sets, but this reduces the size of the list, when
   I have to have a fixed length.
  
   Is there a quick way of checking if a string is already within a list
   without iterating over the items of the list (which will slow the
   application down slightly)?
 
  Hmm. If you are trying to pick 10 elements at random from a larger list,
  use random.sample(problems, 10)
 
  If for some reason that doesn't work for you (maybe you are creating
  problems on the fly?) you could build a set in a loop, adding items
  until it is the size you want:
  problemSet = set()
  while len(problemSet)  10:
 # do something to add a (possibly) new problem to the set
 


I'm creating them on the fly - so this suggestion seems to be the
sensible way forward.

I've not worked with Sets before but will give it a go. Is there a way
of turning the Set back to a list?

TIA
Adam
-- 
http://www.monkeez.org
PGP key: 0x7111B833
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Removing duplicates in a list with a fixed length of items in the list.

2007-01-11 Thread Kent Johnson
Adam Cripps wrote:
 I've not worked with Sets before but will give it a go. Is there a way
 of turning the Set back to a list?

list(mySet)

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Removing duplicates in a list with a fixed length of items in the list.

2007-01-11 Thread Klaus Ramelow
Why not sorting the items and throw out all multiples until you reach 
the fixed length ?

Klaus Ramelow
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor