Created
June 24, 2020 04:21
-
-
Save jack980517/362780bb5f9d47c45d638eab1ccb80ca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!python2 | |
from fractions import Fraction as F | |
def prime_factors(n): | |
#adapted from https://stackoverflow.com/a/16996439/5090149 | |
result=[] | |
#special case: 2 | |
while n%2==0: | |
result.append(2) | |
n//=2 | |
d=3 | |
while d*d<=n: | |
while n%d==0: | |
result.append(d) | |
n//=d | |
d+=2 | |
return result | |
def base_conv(n,b,d="0123456789abcdefghijklmnopqrstuvwxyz"): | |
if b<2 or b>len(d): | |
raise ValueError("Invalid base") | |
if isinstance(n,int) or isinstance(n,long): | |
n=F(n) | |
if not isinstance(n,F): | |
raise ValueError("Float is not accepted; use Fraction for non-integer") | |
if n<=0: | |
if n==0: | |
return digits[0] | |
else: #negative | |
return '-'+base_conv(-n,b,d) | |
result='' | |
if n.denominator==1: #positive integer | |
while n>0: | |
idx=int(n%b) | |
n//=b | |
result=d[idx]+result | |
return result | |
else: #positive non-integer | |
if n>1: #has integer part | |
int_part=n//1 | |
frac_part=n%1 | |
return base_conv(int_part,b,d)+base_conv(frac_part,b,d) | |
else: #0.xxx | |
result='.' | |
denom=F(1,b) | |
#identify recurring fractions | |
pfn=prime_factors(n.denominator) | |
pfb=prime_factors(b) | |
pure_recurring=False | |
recurring=False | |
if not set(pfn)&set(pfb): | |
pure_recurring=True | |
recurring=True | |
if not pure_recurring: | |
for i in pfn: | |
if i not in pfb: | |
recurring=True | |
break | |
length_of_not_recurring_part=0 | |
if recurring and not pure_recurring: | |
length_of_not_recurring_part=max([pfn.count(_) for _ in set(pfb)]) | |
length_of_recurring_part=0 | |
if recurring: | |
temp=n if pure_recurring else n*(b**length_of_not_recurring_part) | |
temp2=b-1 | |
length_of_recurring_part=1 | |
while (temp*temp2).denominator!=1: | |
temp2=temp2*b+b-1 | |
length_of_recurring_part+=1 | |
if recurring: | |
i=0 | |
while n>0: | |
idx=int(n//denom) | |
n-=denom*idx | |
denom*=F(1,b) | |
if i==length_of_not_recurring_part: | |
result+='{' | |
result+=d[idx] | |
i+=1 | |
if i==length_of_not_recurring_part+length_of_recurring_part: | |
result+='}' | |
break | |
else: | |
while n>0: | |
idx=int(n//denom) | |
n-=denom*idx | |
denom*=F(1,b) | |
result+=d[idx] | |
return result | |
if __name__=="__main__": | |
print base_conv(F(123),6) | |
print base_conv(F(1.25),6) | |
print base_conv(F(1,5),12) | |
print base_conv(F(3,2),16) | |
print base_conv(F(6,5),16) | |
print base_conv(255,16) | |
print base_conv(F(1767707668033969,60466176),36) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment