From f69321c69ba16f49da45bd78ea4fd0b4b8a9df27 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 11 Jun 2022 17:35:14 +0100 Subject: [PATCH 1/4] Minor optimization for Fractions.limit_denominator When we construct the upper and lower candidates in limit_denominator, the numerator and denominator are already relatively prime (and the denominator positive) by construction, so there's no need to go through the usual normalisation in the constructor. This saves a couple of potentially expensive gcd calls. Suggested by Michael Scott Asato Cuthbert in GH-93477. --- Lib/fractions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/fractions.py b/Lib/fractions.py index f9ac882ec002fa..7b533bf98cbd9b 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -247,8 +247,8 @@ def limit_denominator(self, max_denominator=1000000): n, d = d, n-a*d k = (max_denominator-q0)//q1 - bound1 = Fraction(p0+k*p1, q0+k*q1) - bound2 = Fraction(p1, q1) + bound1 = Fraction(p0+k*p1, q0+k*q1, _normalize=False) + bound2 = Fraction(p1, q1, _normalize=False) if abs(bound2 - self) <= abs(bound1-self): return bound2 else: From 9ac09a1c7d6e8774a4b0c0233fb638f3c4afd11c Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 12 Jun 2022 08:05:47 +0100 Subject: [PATCH 2/4] More efficient comparison of candidates --- Lib/fractions.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Lib/fractions.py b/Lib/fractions.py index 7b533bf98cbd9b..cd4de4a87d678f 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -245,14 +245,17 @@ def limit_denominator(self, max_denominator=1000000): break p0, q0, p1, q1 = p1, q1, p0+a*p1, q2 n, d = d, n-a*d - k = (max_denominator-q0)//q1 - bound1 = Fraction(p0+k*p1, q0+k*q1, _normalize=False) - bound2 = Fraction(p1, q1, _normalize=False) - if abs(bound2 - self) <= abs(bound1-self): - return bound2 + + # Determine which of the candidate fractions (p0+k*p1)/(q0+k*q1) and + # p1/q1 is closer to self. The distance between the two candidates is + # 1/(q1*(q0+k*q1)), while the distance from p1/q1 to self is + # 1/(q1*(q0+n/d*q1)). So we need to compare q0+k*q1 with 2*(q0+n/d*q1). + # That translates to the following comparison in integers. + if (q0+2*k*q1)*d <= q1*n: + return Fraction(p1, q1, _normalize=False) else: - return bound1 + return Fraction(p0+k*p1, q0+k*q1, _normalize=False) @property def numerator(a): From be8c3327ef1988b731381e75446c58d6dfabab2c Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 12 Jun 2022 08:12:12 +0100 Subject: [PATCH 3/4] Fix typo in comment --- Lib/fractions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/fractions.py b/Lib/fractions.py index cd4de4a87d678f..379a55c68ef919 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -250,7 +250,7 @@ def limit_denominator(self, max_denominator=1000000): # Determine which of the candidate fractions (p0+k*p1)/(q0+k*q1) and # p1/q1 is closer to self. The distance between the two candidates is # 1/(q1*(q0+k*q1)), while the distance from p1/q1 to self is - # 1/(q1*(q0+n/d*q1)). So we need to compare q0+k*q1 with 2*(q0+n/d*q1). + # 1/(q1*(q0+n/d*q1)). So we need to compare 2*(q0+k*q1) with q0+n/d*q1. # That translates to the following comparison in integers. if (q0+2*k*q1)*d <= q1*n: return Fraction(p1, q1, _normalize=False) From 6f70f586783b7c3ff6c23af1ac32f791332ebd00 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 12 Jun 2022 11:19:04 +0100 Subject: [PATCH 4/4] Tweak to remove an extra operation --- Lib/fractions.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Lib/fractions.py b/Lib/fractions.py index 379a55c68ef919..738a0d4c301d43 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -247,12 +247,11 @@ def limit_denominator(self, max_denominator=1000000): n, d = d, n-a*d k = (max_denominator-q0)//q1 - # Determine which of the candidate fractions (p0+k*p1)/(q0+k*q1) and - # p1/q1 is closer to self. The distance between the two candidates is - # 1/(q1*(q0+k*q1)), while the distance from p1/q1 to self is - # 1/(q1*(q0+n/d*q1)). So we need to compare 2*(q0+k*q1) with q0+n/d*q1. - # That translates to the following comparison in integers. - if (q0+2*k*q1)*d <= q1*n: + # Determine which of the candidates (p0+k*p1)/(q0+k*q1) and p1/q1 is + # closer to self. The distance between them is 1/(q1*(q0+k*q1)), while + # the distance from p1/q1 to self is d/(q1*self._denominator). So we + # need to compare 2*(q0+k*q1) with self._denominator/d. + if 2*d*(q0+k*q1) <= self._denominator: return Fraction(p1, q1, _normalize=False) else: return Fraction(p0+k*p1, q0+k*q1, _normalize=False) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy