Re: [Tutor] Removing duplicates
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
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
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
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.
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.
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.
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.
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.
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