Skip to content

Instantly share code, notes, and snippets.

@jack980517
Created June 24, 2020 04:21
Show Gist options
  • Save jack980517/362780bb5f9d47c45d638eab1ccb80ca to your computer and use it in GitHub Desktop.
Save jack980517/362780bb5f9d47c45d638eab1ccb80ca to your computer and use it in GitHub Desktop.
#!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