Since this is a short month, here are some short pieces of code.
A far shorter number naming and approximating function than the previous post – clearly has far less options.
from math import log
def approx(n):
"""48593829509385 -> '48.593 trillion'
if n is a string, that is taken as a power of 1000
From Orthallelous
follows the naming scheme given by Landon Curt Noll
http://www.isthe.com/chongo/tech/math/number/number.html"""
d=r='';i=0
u=['thousand','m','b','tr','quadr','quint','sext','sept','oct','non','dec']
o=['','un','duo','tre','quattuor','quin','sex','septen','octo','novem','dec']
t=['','dec','vigin','trigin','quadragin','quinquagin','sexagin','septuagin','octogin','nonagin']
h=['','cen','duocen','trecen','quadringen','quingen','sescen','septingen','octingen','nongen']
def q(k):return''.join([h[(k//100)%10],o[k%10],t[(k//10)%10]])
if not n:return'0'
elif type(n)==str:c=int(n)-1;a=1
else:
if n<0:d='-';n=abs(n)
c=int(round(log(n,1000),7))-1;a=(n//1000**(c))/1000.
s=('illion'if 20>(c%100)>9 or c<11 else'tillion')if c else''
if c<0:return d+str(n)
elif c<=10:r=u[c]
else:
while c:
c,p=divmod(c,1000)
r=''.join([q(p),('millia'*i if p else''),r]);i+=1
if r[:2]==q(1)and i>1:r=r[2:]
return''.join([d,'{:.3f} '.format(a),r,s])
Examples:
>>> approx(4859)
'4.859 thousand'
>>> approx(56)
'56'
>>> approx(1000230928345)
'1.000 trillion'
>>> approx(99887766554433221100)
'99.887 quintillion'
>>> approx('1002003')
'1.000 milliamilliaduomilliaduotillion'
—————-
Here’s a different approximator, uses SI prefixes. Will return a string such that you can append a unit to it without additional formatting. I am using a ‘u’ instead of a ‘µ’ though. if you want the µ, change the ‘u’ at the end of the 4th line to ‘\xb5’, but this is dependent on your encoding.
from math import log, floor
def si(val):
"Approximates n with SI prefixes\nFrom Orthallelous"
SI={-8:'y',-7:'z',-6:'a',-5:'f',-4:'p',-3:'n',-2:'u',
-1:'m',1:'k',2:'M',3:'G',4:'T',5:'P',6:'E',7:'Z',8:'Y'}
p=int(floor(log(abs(val),1e3)))
if not p:return str(val)+' '
if abs(p)>8:p=p//abs(p)*8
a=(val//1e3**(p-1))/1e3
return'{:.2f} {}'.format(a,SI[p])
Examples:
>>> si(45) '45 ' >>> si(348642121) '348.64 M' >>> si(0.00000000456) '4.56 n' >>> si(938272046)+'eV' '938.27 MeV' >>> si(632.8e-9)+'m' '632.80 nm'
And here’s the reverse!
def rsi(val, unit=None):
"Converts an SI value to a float\nFrom Orthallelous"
SI={'y':-8,'z':-7,'a':-6,'f':-5,'p':-4,'n':-3,'u':-2,'\xb5':-2,
'm':-1,'k':1,'M':2,'G':3,'T':4,'P':5,'E':6,'Z':7,'Y':8}
if unit:val=val.replace(unit,'',1)
for i in SI.keys():
if i in val:n=1e3**SI[i];val=val.replace(i,'');break
else:n=1.
return n*float(val)
Examples:
>>> rsi('632.80 nm','m')
6.328e-07
>>> rsi('938.27 MeV', 'eV')
938270000.0
>>> rsi('500.7 k')
500700.0
>>> rsi('25.4 mm', 'm')
0.0254
—————-
A slightly different DeltaT from here – now has a style option. If st is 0, you’ll get the time written out. If st is 1, you’ll get an abbreviated form of the written format. If st is -1, then you’ll get a digital clock like form.
def DeltaT(sec,st=0):
"75 -> '1 minute, 15 seconds'\nfrom Orthallelous"
if sec==0:return'no elasped time'
S,Q,c,t=[],abs(sec),0,''
N=['second','minute','hour','day','week']
for j in[60,60,24,7]:Q,r=divmod(Q,j);S.append(r)
S.append(Q)
if st<0:
S.reverse();S=[int(i)for i in S]
t=':'.join(list(map('{:02d}'.format,S)))
while len(t)>8 and t[0]in'0:':t=t[1:]
return t
for T in S:
if T==0:c+=1;continue
v=str(int(T))
if c==0 and int(T)!=T:v=str(round(T,2))
n=N[c];c+=1
if T!=1 and not st:n=''.join([n,'s'])
if st:t=''.join([v,n[0],' ',t])
else:t=''.join([v,' ',n,', ',t])
return t.rstrip(', ')
Examples:
>>> DeltaT(3727) '1 hour, 2 minutes, 7 seconds' >>> DeltaT(3727, 1) '1h 2m 7s' >>> DeltaT(3727, -1) '01:02:07'
—————-
And here’s a linear interpolater. Pass it two vectors and it’ll add points between them. Will return a list of tuples; does not return the end point – change the +1 in the “for i in range(n+1):” line to n+2 if you want the endpoint.
def lerp(v1, v2, numPts=10):
"linearly interpolate from v1 to v2\nFrom Orthallelous"
if len(v1)!=len(v2):raise ValueError("different dimensions")
D,V,n=[],[],abs(numPts)
for i,u in enumerate(v1):D.append(v2[i]-u)
for i in range(n+1):
vn=[]
for j,u in enumerate(v1):vn.append(u+D[j]/float(n+1)*i)
V.append(tuple(vn))
return V
Examples:
>>> lerp( (5,) , (7,) , 7)#one dimensional vectors [(5.0,), (5.25,), (5.5,), (5.75,), (6.0,), (6.25,), (6.5,), (6.75,)] >>> lerp( (255,0,0), (0,0,255), 3)#red to green [(255.0, 0.0, 0.0), (191.25, 0.0, 63.75), (127.5, 0.0, 127.5), (63.75, 0.0, 191.25)]
Leave a comment