Python的divmod
函數可以正常工作,而且幾乎是我想要的。但是,對於需要執行的操作,其非整數數字的行爲需要略有不同。運行以下代碼時,您可能會看到它正在嘗試完成的工作。尋找一種不同的divmod函數
>>> function = divmod
>>> from math import pi
>>> function(pi * pi, pi) == (pi, 0)
False
>>>
如何function
以上這樣來定義最終表達式求True
,不False
?如果有人能想出如何得到(pi, 0)
而不是(3.0, 0.4448...)
,那就是答案。
編輯1:現在對於更復雜的示例,下面的代碼應該產生[3, 2, 1, 3, 2, 1]
。
>>> x = 1 * pi ** 5 + \
2 * pi ** 4 + \
3 * pi ** 3 + \
1 * pi ** 2 + \
2 * pi ** 1 + \
3 * pi ** 0
>>> digits = []
>>> while x:
x, y = function(x, pi)
digits.append(y)
>>> digits
[0.3989191524449005, 0.2212554774328268, 2.309739581793931, 0.1504440784612413,
2.858407346410207, 1.0]
>>>
編輯2:下面顯示的代碼,除了它具有意外,但有效輸出工作正常。
import math
def convert_dec_to_pi(number):
digits = get_pi_digits(number)
digits, remainder = correct_pi_digits(digits)
return make_pi_string(digits, remainder)
def get_pi_digits(number):
digits = []
while number:
number, digit = divmod(number, math.pi)
digits.append(digit)
digits.reverse()
return digits
def correct_pi_digits(digits):
last = len(digits) - 1
for index, digit in enumerate(digits):
if index < last and digit % 1 != 0:
a, b = get_digit_options(digit, digits[index + 1])
digits[index:index+2] = a if 0 <= a[1] < math.pi else b
digit, remainder = divmod(digits[-1], 1)
digits[-1] = digit
return digits, remainder
def get_digit_options(digit, next_digit):
a, b = math.floor(digit), math.ceil(digit)
if a not in range(4):
return (b, (digit - b) * math.pi + next_digit), None
if b not in range(4):
return (a, (digit - a) * math.pi + next_digit), None
c, d = ((a, (digit - a) * math.pi + next_digit),
(b, (digit - b) * math.pi + next_digit))
return (c, d) if digit - a < 0.5 else (d, c)
def make_pi_string(digits, remainder):
return '{} base \u03C0 + {} base 10'.format(
''.join(str(int(d)) for d in digits), remainder)
以下函數可用於反轉操作並檢查結果。
import re
def convert_pi_to_dec(string):
match = re.search('^(\\d+) base \u03C0 \\+ (0\\.\\d+) base 10$', string)
if not match:
raise ValueError()
digits, remainder = match.groups()
return sum(int(x) * math.pi ** y for y, x in enumerate(reversed(digits))) \
+ float(remainder)
下面的代碼不會引發AssertionError
,所以很明顯,一切工作正常。
for n in range(1, 36):
value = convert_dec_to_pi(n)
print(value)
assert convert_pi_to_dec(value) == n
那麼這就讓我看看下面的例子。輸出可以在沒有問題的情況下被轉換回來,但是人們會預料到稍有不同。
>>> convert_dec_to_pi(math.pi * math.pi)
'30 base π + 0.44482644031997864 base 10'
>>> convert_pi_to_dec(_) == math.pi * math.pi
True
>>>
該字符串應該是100 base π + 0.0 base 10
。輸出是準確的,但在這一點上不是「正確的」。
編輯3:下面的示例可能會提供一些額外的信息,以瞭解我所追求的內容。運行一個具有不同π次冪的循環後,我希望所有輸出都是10... base π + 0.0 base 10
。結果與此不同,如下所示。
>>> for power in range(20):
print(convert_dec_to_pi(math.pi ** power))
1 base π + 0.0 base 10
10 base π + 0.0 base 10
30 base π + 0.44482644031997864 base 10
231 base π + 0.8422899173517213 base 10
2312 base π + 0.6461318165449161 base 10
23122 base π + 0.029882968108176033 base 10
231220 base π + 0.0938801130760924 base 10
2312130 base π + 0.7397595138779653 base 10
23121302 base π + 0.3240230542211062 base 10
231213021 base π + 0.017948446735832846 base 10
2312130210 base π + 0.05638670840988885 base 10
23121302100 base π + 0.17714406890720072 base 10
231213021000 base π + 0.5565145054551264 base 10
2312130133130 base π + 0.6366321966964654 base 10
23121301331302 base π + 3.9032618162071486e-05 base 10
231213013313020 base π + 0.00012262302157861615 base 10
2312130133123211 base π + 0.24905356925301847 base 10
23121301331232110 base π + 0.7824248909895828 base 10
231213013312321102 base π + 0.4580601707952492 base 10
2312130133123211021 base π + 0.4390387422112354 base 10
>>> convert_pi_to_dec('2312130133123211021 base π + 0.4390387422112354 base 10')
2791563949.5978436
>>> convert_pi_to_dec('10000000000000000000 base π + 0.0 base 10')
2791563949.5978436
>>>
還顯示了最後兩個字符串是如何等價的,但輸出應該是第二個字符串的形式。我發現10000000000000000000 base π
和2312130133123211021 base π
之間的差別是0.4390387422112354 base 10
,但這種差別對錶示有很大的影響。輸出應該如下所示。
1 base π + 0.0 base 10
10 base π + 0.0 base 10
100 base π + 0.0 base 10
1000 base π + 0.0 base 10
10000 base π + 0.0 base 10
100000 base π + 0.0 base 10
1000000 base π + 0.0 base 10
10000000 base π + 0.0 base 10
100000000 base π + 0.0 base 10
1000000000 base π + 0.0 base 10
10000000000 base π + 0.0 base 10
100000000000 base π + 0.0 base 10
1000000000000 base π + 0.0 base 10
10000000000000 base π + 0.0 base 10
100000000000000 base π + 0.0 base 10
1000000000000000 base π + 0.0 base 10
10000000000000000 base π + 0.0 base 10
100000000000000000 base π + 0.0 base 10
1000000000000000000 base π + 0.0 base 10
10000000000000000000 base π + 0.0 base 10
有沒有辦法,我失去了一些東西,有沒有一個解決這個問題,還是應該這被認爲是傻瓜的差事?
所以基本上,你想剩下的總是0?那爲什麼要用'divmod'?只需使用部門! – kindall 2012-08-08 13:37:00
半認真的答案:使用分段函數'func = lambda x,y:(pi,0)if x == pi * pi and y == pi else divmod(x,y)'。如果這還不夠,請顯示更多樣本輸入/輸出。從一個數據點推導出方程很困難。 – Kevin 2012-08-08 13:44:52
請參閱編輯。第一個例子中,你的函數可以很好地工作。不過,這是我之後的第二個應用程序。 – 2012-08-08 14:01:50