繁体   English   中英

为什么elif在if语句之前运行? 蟒蛇

[英]Why is elif running before if statement? Python

项目Euler问题33要求求解器找到“好奇分数”:这些分数等于通过删除分子和分母中同时出现的数字而获得的分数(例如49/98,通过删除数字将其“取消”为4/8) 9s)。

注意:这不是解决Project Euler问题最快的竞赛。 我已经将此代码重写为一个与Nickie一样快的解决方案。 这是通过删除for循环和if float(numer)...条件来完成的。 看起来像这样:

def curious(numer,denom):
    n = str(numer)
    d = str(denom)

    if len(n) == 2 and len(d) == 2:
        if n[1] == d[0]:
            if n != d:
                if d[1] != "0":
                    if Fraction(int(n[0]), int(d[1])) \
                    == \
                    Fraction(numer, denom):
                            return n + d

我仍然不理解条件问题。

我对Python编程并不陌生,这是我第一次遇到这样的事情。 在下面定义的函数中,有成对的if和elif语句:

import time
from fractions import Fraction

def curious(numer,denom):
    n = str(numer)
    d = str(denom)

    if len(n) == 2 and len(d) == 2:
        if n[1] == d[0]:
            for i in range(2, numer+1):
                if float(numer)/i == float(int(n[0])) \
                and float(denom)/i == float(int(d[1])):
                    if n != d:
                        return n + "/" + d

                elif d[1] != "0":
                    if Fraction(int(n[0]), int(d[1])) \
                    == \
                    Fraction(numer, denom):
                        if n != d:
                            return n + d


start = time.time()

nums = []
denoms = []
for i in range(10, 100):
    for j in range(10, 100):
        if i < j:
            if type(curious(i, j)) == str:
                frac = (curious(i,j))
                nums.append(frac[0]+frac[1])
                denoms.append(frac[2]+frac[3])
                print frac

pro = 1
duct = 1

for i in range(0, len(nums)):
    pro *= int(nums[i])
    duct *= int(denoms[i])


print Fraction(pro, duct)

elapsed = time.time() - start
print "The elapsed time is %s seconds." % (elapsed)

当我在注释掉elif语句的情况下运行代码时,结果是这样的:

16/64,
19/95,
26/65,
The elapsed time is 0.0500001907349 seconds.

但是,当包含elif时,if语句将被忽略,结果是这样的:

1664,
1995,
2665,
4998,
The elapsed time is 0.59700012207 seconds.

似乎Python倾向于采用低效率的路由,即使在两种情况下均满足if语句的条件。 谁能帮我解决这个难题?

理想情况下,我希望结果为:

16/64,
19/95,
26/65,
4998,
The elapsed time is 0.0500001907349 seconds.

这是一个奇怪的结构化答案,因为它是增量编写的。 我为此表示歉意。 即使这样,我还是值得按此顺序阅读。 每个部分都用水平尺隔开,各有不同。


浮点算法中的相等比较是常见的麻烦来源,应避免使用。 代替测试:

float(numer)/i == float(int(n[0])) and float(denom)/i == float(int(d[1]))

为什么不以下? 更简单和等效(在数学中,但在Python中不!):

numer == i * int(n[0]) and denom == i * int(d[1])

最重要的是,不仅浮点运算会带来麻烦,而且从intfloat太频繁也不利于性能。


我不明白为什么您希望您的程序在删除elif子句时能输出相同的结果。 当您拥有和没有elif时,它会执行两种不同的操作。 您只是返回相同的结果(n / d),所以看不到差异。

if语句未“被绕过”。 但是,如果它在for循环的第一次迭代中未返回任何内容,则elif语句(在每次迭代中执行相同的操作)将有机会返回其值。 然后, if语句将不再执行。


由于现在已经提供了有关该问题的更多信息(这是作为对Euler项目的问题#33的解决方案的一部分),我将继续使用该问题的原始版本,并尝试重构curious函数,我认为这是写得不好的。 我相信以下函数是等效的,并且速度更快,因为for循环仅计算依赖于i事物:

def curious(numer,denom):
    n = str(numer)
    d = str(denom)

    if len(n) == 2 == len(d) and n[1] == d[0] and n != d:
       for i in range(2, numer+1):
           if numer == i*int(n[0]) and denom == i*int(d[1]):
               return n + "/" + d
           elif i == 2 and d[1] != "0":
               if Fraction(int(n[0]), int(d[1])) == Fraction(numer, denom):
                   return n + d

使用此功能,Cawb07的程序可以更快地产生相同的输出(四个分数加1/100,这是问题的答案)。


既然我了解了curious正在尝试做什么,那么让我提出一个更好的方法。 让我们假设要寻求一种蛮力解决方案。 它可以很容易地进行排列,以便总是使用两个两位数的参数来调用curious ,其numer < denom为true,并且它返回一个布尔结果,表示该分数是否为curious。 此外,没有必要为一个for循环的curious ,这可以大大简化。

import time
from fractions import Fraction

def curious(numer, denom):
    n = str(numer)
    d = str(denom)
    return (n[0] == d[1] != '0' and denom * int(n[1]) == numer * int(d[0])) \
        or (n[0] == d[0] != '0' and denom * int(n[1]) == numer * int(d[1])) \
        or (n[1] == d[0] != '0' and denom * int(n[0]) == numer * int(d[1])) \
        or (n[1] == d[1] != '0' and denom * int(n[0]) == numer * int(d[0]))

start = time.time()

for i in range(10, 100):
    for j in range(i+1, 100):
        if curious(i, j):
           print i, "/", j

elapsed = time.time() - start
print "The elapsed time is", elapsed, "seconds."

该程序仅打印四个奇怪的分数,比上一个要快得多。

还要注意,为了将好奇分数的乘积减少到最低的公共术语,您可以轻松地计算出分母和分母,然后除以它们的GCD,这可以使用Euclid算法找到。

Cawb07:也可以使用fractions.gcd(n,d) :)。

在我的以下代码中,根据提供给ELIF的值, elif section处于活动状态或停用状态

import time
from fractions import Fraction

def curious(numer,denom,disp=None):
    n = str(numer)
    d = str(denom)
    fracs = []
    if n!=d and n[1] == d[0]:
        ELIF = 1

        fn0 = float(n[0])
        fd1 = float(d[1])
        if disp:
            print ('---------------------------------------\n'
                   'n == %s  d == %s\n'
                   "float('%s'[0]) == %f  float('%s'[1]) == %f"
                   % ( n,d,n,fn0,d,fd1 ) )

        for i in range(2, numer+1):
            if disp:
                print ('i== %2d   '
                       '%s./%2d==%10f   %s./%2d==%10f  %s' %
                       (i,n,i,float(n)/i,d,i,float(d)/i,
                        float(n)/i==fn0 and float(d)/i==fd1) )

            if float(numer)/i==fn0 and float(denom)/i==fd1:
                if disp:
                    print ('  %s\n'
                           '  - %s/%s returned by if section -' %
                           ('- elif part is active -' if ELIF
                            else '- elif part is not active -',
                            n,d))
                return n + "/" + d

            elif ELIF and d[1] != "0":
                if Fraction( n[0] + '/' + d[1] ) \
                   == \
                   Fraction(numer, denom):
                    if disp:
                        print ('  %s\n'
                               "  Fraction('%s/%s') == %s\n"
                               "  Fraction(%s, %s) == %s\n"
                               '  - %s%s returned by elif section -' %
                               ('- elif part is active -' if ELIF
                                else '- elif part is not active -',
                                n[0],d[1],Fraction( n[0] + '/' + d[1] ),
                                numer,denom,Fraction(numer, denom),n,d) )
                    return n + d

        else:
            if n+d=='4998':
                if disp:
                    print ('  - elif part is active -' if ELIF
                           else '  - elif part is not active -')
                    print '  - No convenient divisor found for 49 98 : returned by else section -'
                return 'No convenient divisor found for 49 98'

start = time.time()

nums,denoms = [],[]
fracs = []
for i in range(10, 100):
    for j in range(10, 100):
        if curious(i,j):
            frac = (curious(i,j,'display'))
            print('frac == %s' % frac)
            fracs.append(frac)
            deb,end = frac[0:2],frac[-2:]
            try:
                int(deb)
                nums.append(deb)
                denoms.append(end)
            except:
                print "can't record %r==frac[0:2] as numerator" % (deb,)

print '\ndetected :\n  %s' % '\n  '.join(fracs)

pro,duct = 1,1
print '\nnums ==',nums
print 'denoms ==',denoms

for i in range(0, len(nums)):
    pro *= int(nums[i])
    duct *= int(denoms[i])
print 'pro,duct ==',pro,duct
print 'Fraction(pro, duct) ==',Fraction(pro, duct)

elapsed = time.time() - start
print "The elapsed time is %s seconds." % (elapsed)

ELIF = 0结果

---------------------------------------
n == 16  d == 64
float('16'[0]) == 1.000000  float('64'[1]) == 4.000000
i==  2   16./ 2==  8.000000   64./ 2== 32.000000  False
i==  3   16./ 3==  5.333333   64./ 3== 21.333333  False
i==  4   16./ 4==  4.000000   64./ 4== 16.000000  False
i==  5   16./ 5==  3.200000   64./ 5== 12.800000  False
i==  6   16./ 6==  2.666667   64./ 6== 10.666667  False
i==  7   16./ 7==  2.285714   64./ 7==  9.142857  False
i==  8   16./ 8==  2.000000   64./ 8==  8.000000  False
i==  9   16./ 9==  1.777778   64./ 9==  7.111111  False
i== 10   16./10==  1.600000   64./10==  6.400000  False
i== 11   16./11==  1.454545   64./11==  5.818182  False
i== 12   16./12==  1.333333   64./12==  5.333333  False
i== 13   16./13==  1.230769   64./13==  4.923077  False
i== 14   16./14==  1.142857   64./14==  4.571429  False
i== 15   16./15==  1.066667   64./15==  4.266667  False
i== 16   16./16==  1.000000   64./16==  4.000000  True
  - elif part is not active -
  - 16/64 returned by if section -
frac == 16/64
---------------------------------------
n == 19  d == 95
float('19'[0]) == 1.000000  float('95'[1]) == 5.000000
i==  2   19./ 2==  9.500000   95./ 2== 47.500000  False
i==  3   19./ 3==  6.333333   95./ 3== 31.666667  False
i==  4   19./ 4==  4.750000   95./ 4== 23.750000  False
i==  5   19./ 5==  3.800000   95./ 5== 19.000000  False
i==  6   19./ 6==  3.166667   95./ 6== 15.833333  False
i==  7   19./ 7==  2.714286   95./ 7== 13.571429  False
i==  8   19./ 8==  2.375000   95./ 8== 11.875000  False
i==  9   19./ 9==  2.111111   95./ 9== 10.555556  False
i== 10   19./10==  1.900000   95./10==  9.500000  False
i== 11   19./11==  1.727273   95./11==  8.636364  False
i== 12   19./12==  1.583333   95./12==  7.916667  False
i== 13   19./13==  1.461538   95./13==  7.307692  False
i== 14   19./14==  1.357143   95./14==  6.785714  False
i== 15   19./15==  1.266667   95./15==  6.333333  False
i== 16   19./16==  1.187500   95./16==  5.937500  False
i== 17   19./17==  1.117647   95./17==  5.588235  False
i== 18   19./18==  1.055556   95./18==  5.277778  False
i== 19   19./19==  1.000000   95./19==  5.000000  True
  - elif part is not active -
  - 19/95 returned by if section -
frac == 19/95
---------------------------------------
n == 26  d == 65
float('26'[0]) == 2.000000  float('65'[1]) == 5.000000
i==  2   26./ 2== 13.000000   65./ 2== 32.500000  False
i==  3   26./ 3==  8.666667   65./ 3== 21.666667  False
i==  4   26./ 4==  6.500000   65./ 4== 16.250000  False
i==  5   26./ 5==  5.200000   65./ 5== 13.000000  False
i==  6   26./ 6==  4.333333   65./ 6== 10.833333  False
i==  7   26./ 7==  3.714286   65./ 7==  9.285714  False
i==  8   26./ 8==  3.250000   65./ 8==  8.125000  False
i==  9   26./ 9==  2.888889   65./ 9==  7.222222  False
i== 10   26./10==  2.600000   65./10==  6.500000  False
i== 11   26./11==  2.363636   65./11==  5.909091  False
i== 12   26./12==  2.166667   65./12==  5.416667  False
i== 13   26./13==  2.000000   65./13==  5.000000  True
  - elif part is not active -
  - 26/65 returned by if section -
frac == 26/65
---------------------------------------
n == 49  d == 98
float('49'[0]) == 4.000000  float('98'[1]) == 8.000000
i==  2   49./ 2== 24.500000   98./ 2== 49.000000  False
i==  3   49./ 3== 16.333333   98./ 3== 32.666667  False
i==  4   49./ 4== 12.250000   98./ 4== 24.500000  False
i==  5   49./ 5==  9.800000   98./ 5== 19.600000  False
i==  6   49./ 6==  8.166667   98./ 6== 16.333333  False
i==  7   49./ 7==  7.000000   98./ 7== 14.000000  False
i==  8   49./ 8==  6.125000   98./ 8== 12.250000  False
i==  9   49./ 9==  5.444444   98./ 9== 10.888889  False
i== 10   49./10==  4.900000   98./10==  9.800000  False
i== 11   49./11==  4.454545   98./11==  8.909091  False
i== 12   49./12==  4.083333   98./12==  8.166667  False
i== 13   49./13==  3.769231   98./13==  7.538462  False
i== 14   49./14==  3.500000   98./14==  7.000000  False
i== 15   49./15==  3.266667   98./15==  6.533333  False
i== 16   49./16==  3.062500   98./16==  6.125000  False
i== 17   49./17==  2.882353   98./17==  5.764706  False
i== 18   49./18==  2.722222   98./18==  5.444444  False
i== 19   49./19==  2.578947   98./19==  5.157895  False
i== 20   49./20==  2.450000   98./20==  4.900000  False
i== 21   49./21==  2.333333   98./21==  4.666667  False
i== 22   49./22==  2.227273   98./22==  4.454545  False
i== 23   49./23==  2.130435   98./23==  4.260870  False
i== 24   49./24==  2.041667   98./24==  4.083333  False
i== 25   49./25==  1.960000   98./25==  3.920000  False
i== 26   49./26==  1.884615   98./26==  3.769231  False
i== 27   49./27==  1.814815   98./27==  3.629630  False
i== 28   49./28==  1.750000   98./28==  3.500000  False
i== 29   49./29==  1.689655   98./29==  3.379310  False
i== 30   49./30==  1.633333   98./30==  3.266667  False
i== 31   49./31==  1.580645   98./31==  3.161290  False
i== 32   49./32==  1.531250   98./32==  3.062500  False
i== 33   49./33==  1.484848   98./33==  2.969697  False
i== 34   49./34==  1.441176   98./34==  2.882353  False
i== 35   49./35==  1.400000   98./35==  2.800000  False
i== 36   49./36==  1.361111   98./36==  2.722222  False
i== 37   49./37==  1.324324   98./37==  2.648649  False
i== 38   49./38==  1.289474   98./38==  2.578947  False
i== 39   49./39==  1.256410   98./39==  2.512821  False
i== 40   49./40==  1.225000   98./40==  2.450000  False
i== 41   49./41==  1.195122   98./41==  2.390244  False
i== 42   49./42==  1.166667   98./42==  2.333333  False
i== 43   49./43==  1.139535   98./43==  2.279070  False
i== 44   49./44==  1.113636   98./44==  2.227273  False
i== 45   49./45==  1.088889   98./45==  2.177778  False
i== 46   49./46==  1.065217   98./46==  2.130435  False
i== 47   49./47==  1.042553   98./47==  2.085106  False
i== 48   49./48==  1.020833   98./48==  2.041667  False
i== 49   49./49==  1.000000   98./49==  2.000000  False
  - elif part is not active -
  - No convenient divisor found for 49 98 : returned by else section -
frac == No convenient divisor found for 49 98
can't record 'No'==frac[0:2] as numerator

detected :
  16/64
  19/95
  26/65
  No convenient divisor found for 49 98

nums == ['16', '19', '26']
denoms == ['64', '95', '65']
pro,duct == 7904 395200
Fraction(pro, duct) == 1/50
The elapsed time is 2.40599989891 seconds.

ELIF = 1结果

---------------------------------------
n == 16  d == 64
float('16'[0]) == 1.000000  float('64'[1]) == 4.000000
i==  2   16./ 2==  8.000000   64./ 2== 32.000000  False
  - elif part is active -
  Fraction('1/4') == 1/4
  Fraction(16, 64) == 1/4
  - 1664 returned by elif section -
frac == 1664
---------------------------------------
n == 19  d == 95
float('19'[0]) == 1.000000  float('95'[1]) == 5.000000
i==  2   19./ 2==  9.500000   95./ 2== 47.500000  False
  - elif part is active -
  Fraction('1/5') == 1/5
  Fraction(19, 95) == 1/5
  - 1995 returned by elif section -
frac == 1995
---------------------------------------
n == 26  d == 65
float('26'[0]) == 2.000000  float('65'[1]) == 5.000000
i==  2   26./ 2== 13.000000   65./ 2== 32.500000  False
  - elif part is active -
  Fraction('2/5') == 2/5
  Fraction(26, 65) == 2/5
  - 2665 returned by elif section -
frac == 2665
---------------------------------------
n == 49  d == 98
float('49'[0]) == 4.000000  float('98'[1]) == 8.000000
i==  2   49./ 2== 24.500000   98./ 2== 49.000000  False
  - elif part is active -
  Fraction('4/8') == 1/2
  Fraction(49, 98) == 1/2
  - 4998 returned by elif section -
frac == 4998

detected :
  1664
  1995
  2665
  4998

nums == ['16', '19', '26', '49']
denoms == ['64', '95', '65', '98']
pro,duct == 387296 38729600
Fraction(pro, duct) == 1/100
The elapsed time is 6.40599989891 seconds.

ELIF为False时,
if section返回结果16/64 19/95 26/65 ,格式背叛了这个原点。

ELIF为True时,
elif section返回结果1664 1995 2665 4998 ,它也通过格式显示。
它由elif section返回的事实使您得出结论, if section未运行。

您的结论是错误的,因为您错误地认为

“在两种情况下都满足if语句的条件”

不,不是,因为您不允许循环测试i所有可能值:对于第一个值i==2 ,测试结果始终为False,则始终在后面输入elif section第一个值(尼基已经解释了这一点)。
输入的值是相同的,但没有满足提供相同证据所需的条件。

为了使循环有可能完全运行,有必要使elif section缩进。
请注意,在下面的代码中,在nums后面添加frac[0:2]和在denoms后面添加frac[0:2] frac[-2:]允许执行不会因为错误而停止,并且结果就是您正在等待的结果: 16/64 19/95 26/65 4998

def curious(numer,denom,disp=None):
    n = str(numer)
    d = str(denom)
    fracs = []
    if n!=d and n[1] == d[0]:
        ELIF = 1

        fn0 = float(n[0])
        fd1 = float(d[1])
        if disp:
            print ('---------------------------------------\n'
                   'n == %s  d == %s\n'
                   "float('%s'[0]) == %f  float('%s'[1]) == %f"
                   % ( n,d,n,fn0,d,fd1 ) )

        for i in range(2, numer+1):
            if disp:
                print ('i== %2d   '
                       '%s./%2d==%10f   %s./%2d==%10f  %s' %
                       (i,n,i,float(n)/i,d,i,float(d)/i,
                        float(n)/i==fn0 and float(d)/i==fd1) )
            if float(numer)/i==fn0 and float(denom)/i==fd1:
                if disp:
                    print ('  %s\n'
                           '  - %s/%s returned by if section -' %
                           ('- elif part is active -' if ELIF
                            else '- elif part is not active -',
                            n,d))
                return n + "/" + d

        if ELIF and d[1] != "0":
            if Fraction( n[0] + '/' + d[1] ) \
               == \
               Fraction(numer, denom):
                if disp:
                    print ('  %s\n'
                           "  Fraction('%s/%s') == %s\n"
                           "  Fraction(%s, %s) == %s\n"
                           '  - %s%s returned by elif section -' %
                           ('- elif part is active -' if ELIF
                            else '- elif part is not active -',
                            n[0],d[1],Fraction( n[0] + '/' + d[1] ),
                            numer,denom,Fraction(numer, denom),n,d) )
                return n + d

        else:
            if n+d=='4998':
                if disp:
                    print ('  - elif part is active -' if ELIF
                           else '  - elif part is not active -')
                    print '  - No convenient divisor found for 49 98 : returned by else section -'
                return 'No convenient divisor found for 49 98'

显示

(skiped lines)
---------------------------------------
n == 26  d == 65
float('26'[0]) == 2.000000  float('65'[1]) == 5.000000
i==  2   26./ 2== 13.000000   65./ 2== 32.500000  False
i==  3   26./ 3==  8.666667   65./ 3== 21.666667  False
i==  4   26./ 4==  6.500000   65./ 4== 16.250000  False
i==  5   26./ 5==  5.200000   65./ 5== 13.000000  False
i==  6   26./ 6==  4.333333   65./ 6== 10.833333  False
i==  7   26./ 7==  3.714286   65./ 7==  9.285714  False
i==  8   26./ 8==  3.250000   65./ 8==  8.125000  False
i==  9   26./ 9==  2.888889   65./ 9==  7.222222  False
i== 10   26./10==  2.600000   65./10==  6.500000  False
i== 11   26./11==  2.363636   65./11==  5.909091  False
i== 12   26./12==  2.166667   65./12==  5.416667  False
i== 13   26./13==  2.000000   65./13==  5.000000  True
  - elif part is active -
  - 26/65 returned by if section -
frac == 26/65
---------------------------------------
n == 49  d == 98
float('49'[0]) == 4.000000  float('98'[1]) == 8.000000
i==  2   49./ 2== 24.500000   98./ 2== 49.000000  False
i==  3   49./ 3== 16.333333   98./ 3== 32.666667  False
i==  4   49./ 4== 12.250000   98./ 4== 24.500000  False
i==  5   49./ 5==  9.800000   98./ 5== 19.600000  False
i==  6   49./ 6==  8.166667   98./ 6== 16.333333  False
i==  7   49./ 7==  7.000000   98./ 7== 14.000000  False
i==  8   49./ 8==  6.125000   98./ 8== 12.250000  False
i==  9   49./ 9==  5.444444   98./ 9== 10.888889  False
i== 10   49./10==  4.900000   98./10==  9.800000  False
i== 11   49./11==  4.454545   98./11==  8.909091  False
i== 12   49./12==  4.083333   98./12==  8.166667  False
i== 13   49./13==  3.769231   98./13==  7.538462  False
i== 14   49./14==  3.500000   98./14==  7.000000  False
i== 15   49./15==  3.266667   98./15==  6.533333  False
i== 16   49./16==  3.062500   98./16==  6.125000  False
i== 17   49./17==  2.882353   98./17==  5.764706  False
i== 18   49./18==  2.722222   98./18==  5.444444  False
i== 19   49./19==  2.578947   98./19==  5.157895  False
i== 20   49./20==  2.450000   98./20==  4.900000  False
i== 21   49./21==  2.333333   98./21==  4.666667  False
i== 22   49./22==  2.227273   98./22==  4.454545  False
i== 23   49./23==  2.130435   98./23==  4.260870  False
i== 24   49./24==  2.041667   98./24==  4.083333  False
i== 25   49./25==  1.960000   98./25==  3.920000  False
i== 26   49./26==  1.884615   98./26==  3.769231  False
i== 27   49./27==  1.814815   98./27==  3.629630  False
i== 28   49./28==  1.750000   98./28==  3.500000  False
i== 29   49./29==  1.689655   98./29==  3.379310  False
i== 30   49./30==  1.633333   98./30==  3.266667  False
i== 31   49./31==  1.580645   98./31==  3.161290  False
i== 32   49./32==  1.531250   98./32==  3.062500  False
i== 33   49./33==  1.484848   98./33==  2.969697  False
i== 34   49./34==  1.441176   98./34==  2.882353  False
i== 35   49./35==  1.400000   98./35==  2.800000  False
i== 36   49./36==  1.361111   98./36==  2.722222  False
i== 37   49./37==  1.324324   98./37==  2.648649  False
i== 38   49./38==  1.289474   98./38==  2.578947  False
i== 39   49./39==  1.256410   98./39==  2.512821  False
i== 40   49./40==  1.225000   98./40==  2.450000  False
i== 41   49./41==  1.195122   98./41==  2.390244  False
i== 42   49./42==  1.166667   98./42==  2.333333  False
i== 43   49./43==  1.139535   98./43==  2.279070  False
i== 44   49./44==  1.113636   98./44==  2.227273  False
i== 45   49./45==  1.088889   98./45==  2.177778  False
i== 46   49./46==  1.065217   98./46==  2.130435  False
i== 47   49./47==  1.042553   98./47==  2.085106  False
i== 48   49./48==  1.020833   98./48==  2.041667  False
i== 49   49./49==  1.000000   98./49==  2.000000  False
  - elif part is active -
  Fraction('4/8') == 1/2
  Fraction(49, 98) == 1/2
  - 4998 returned by elif section -
frac == 4998

detected :
  16/64
  19/95
  26/65
  4998

nums == ['16', '19', '26', '49']
denoms == ['64', '95', '65', '98']
pro,duct == 387296 38729600
Fraction(pro, duct) == 1/100
The elapsed time is 2.45300006866 seconds.

但是,格式的差异表明,最后一个值是由另一个节( elif section )返回的,而不是3个第一个值(由if section返回)。
这值得澄清。
显示器显示不存在的值i为其49./i将是498./i将是8 :这意味着,没有理由认为n[0]==4将是的除数n==49d[1]==8的除数d==98
因此,问题的根源不是不可能用二进制表示形式精确地表示十进制值(导致难以在浮点算法中进行比较),而是算法问题。

仅当执行测试49./i==1.0 and 98.i==2.00 ,才会导致返回由if section格式化为3个第一个值的49/98值。 因此,我认为以下代码具有正确的算法。 但是,无论给ELIF提供什么值,都不会执行elif sectionelse section 那仅意味着if section中的算法等同于带有Fractionelif section的原理。

def curious(numer,denom,disp=None):
    n = str(numer)
    d = str(denom)
    fracs = []
    if n!=d and n[1] == d[0]:
        ELIF = 1

        fn0 = float(n[0])
        fd1 = float(d[1])
        GCD = gcd(fn0,fd1)
        fn0DD = fn0/GCD
        fd1DD = fd1/GCD

        if disp:
            print ('---------------------------------------\n'
                   'n == %s  d == %s\n'
                   "float('%s'[0]) == %f  float('%s'[1]) == %f"
                   % ( n,d,n,fn0,d,fd1 ) )

        for i in range(2, numer+1):
            if disp:
                print ('i== %2d   '
                       '%s./%2d==%10f   %s./%2d==%10f  %s' %
                       (i,n,i,float(n)/i,d,i,float(d)/i,
                        float(n)/i==fn0DD and float(d)/i==fd1DD) )
            if float(numer)/i==fn0DD and float(denom)/i==fd1DD:
                if disp:
                    print ('  %s\n'
                           '  - %s/%s returned by if section -' %
                           ('- elif part is active -' if ELIF
                            else '- elif part is not active -',
                            n,d))
                return n + "/" + d

        if ELIF and d[1] != "0":
            if Fraction( n[0] + '/' + d[1] ) \
               == \
               Fraction(numer, denom):
                if disp:
                    print ('  %s\n'
                           "  Fraction('%s/%s') == %s\n"
                           "  Fraction(%s, %s) == %s\n"
                           '  - %s%s returned by elif section -' %
                           ('- elif part is active -' if ELIF
                            else '- elif part is not active -',
                            n[0],d[1],Fraction( n[0] + '/' + d[1] ),
                            numer,denom,Fraction(numer, denom),n,d) )
                return n + d

等待显示

(skipped lines)
i== 44   49./44==  1.113636   98./44==  2.227273  False
i== 45   49./45==  1.088889   98./45==  2.177778  False
i== 46   49./46==  1.065217   98./46==  2.130435  False
i== 47   49./47==  1.042553   98./47==  2.085106  False
i== 48   49./48==  1.020833   98./48==  2.041667  False
i== 49   49./49==  1.000000   98./49==  2.000000  True
  - elif part is active -
  - 49/98 returned by if section -
frac == 49/98

detected :
  16/64
  19/95
  26/65
  49/98

nums == ['16', '19', '26', '49']
denoms == ['64', '95', '65', '98']
pro,duct == 387296 38729600
Fraction(pro, duct) == 1/100
The elapsed time is 2.39100003242 seconds.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM