[英]Python internal metric unit conversion function
我正在嘗試構建一個函數,以對波長到頻率轉換程序進行內部度量轉換,並且一直很難使其正常工作。 它非常慢,不會為輸出分配正確的標簽。 如果任何人都可以用另一種方法來解決這個問題,或者是為什么發生這種情況的原因,而我所做的任何修復都將是驚人的!
def convert_SI_l(n):
if n in range( int(1e-12),int(9e-11)):
return n/0.000000000001, 'pm'
else:
if n in range(int(1e-10),int(9e-8)):
return n/0.000000001 , 'nm'
else:
if n in range(int(1e-7),int(9e-5)):
return n/0.000001, 'um'
else:
if n in range(int(1e-4),int(9e-3)):
return n/0.001, 'mm'
else:
if n in range(int(0.01), int(0.99)):
return n/0.01, 'cm'
else:
if n in range(1,999):
return n/1000, 'm'
else:
if n in range(1000,299792459):
return n/1000, 'km'
else:
return n , 'm'
def convert_SI_f(n):
if n in range( 1,999):
return n, 'Hz'
else:
if n in range(1000,999999):
return n/1000 , 'kHz'
else:
if n in range(int(1e6),999999999):
return n/1e6, 'MHz'
else:
if n in range(int(1e9),int(1e13)):
return n/1e9, 'GHz'
else:
return n, 'Hz'
c=299792458
i=input("Are we starting with a frequency or a wavelength? ( F / L ): ")
#Error statements
if i.lower() == ("f"):
True
else:
if not i.lower() == ("l"):
print ("Error invalid input")
#Cases
if i.lower() == ("f"):
f = float(input("Please input frequency (in Hz): "))
size_l = c/f
print(convert_SI_l(size_l))
if i.lower() == ("l"):
l = float(input("Please input wavelength (in meters): "))
size_f = ( l/c)
print(convert_SI_f(size_f))
編輯:實際上, range
是通常在義化中用於生成數字的函數。
所以,當你寫
if n in range(min_value, max_value)
該函數生成的所有整數,直到找到一個匹配或達到
MAX_VALUE。
的
range
類型表示數字的不可變序列,並通常用於在循環的特定次數for
環路。
而不是寫:
if n in range(int(1e-10),int(9e-8)):
return n/0.000000001 , 'nm'
您應該寫:
if 1e-10 <= n < 9e-8:
return n/0.000000001 , 'nm'
還請記住, range
僅適用於整數,不適用於浮點數。
更多編輯:
對於您的特定用例,您可以定義*(值,符號)對的字典,如下所示:
import collections
symbols = collections.OrderedDict(
[(1e-12, u'p'),
(1e-9, u'n'),
(1e-6, u'μ'),
(1e-3, u'm'),
(1e-2, u'c'),
(1e-1, u'd'),
(1e0, u''),
(1e1, u'da'),
(1e2, u'h'),
(1e3, u'k'),
(1e6, u'M'),
(1e9, u'G'),
(1e12, u'T')])
使用bisect.bisect
函數可在該有序集合中找到值的“插入”點。 該插入點可用於獲取簡化值和要使用的SI符號。
例如:
import bisect
def convert_to_si(value):
if value < 0:
value, symbol = convert_to_si(-value)
return -value, symbol
elif value > 0:
orders = list(symbols.keys())
order_index = bisect.bisect(orders, value / 10.0)
order = orders[min(order_index, len(orders) - 1)]
return value / order, symbols[order]
else:
return value, u""
示范:
for value in [1e-12, 3.14e-11, 0, 2, 20, 3e+9]:
print(*convert_to_si(value), sep="")
你得到:
1.0p
0.0314n
0
2.0
2.0da
3.0G
您可以根據需要調整此功能…
您正在以接近自然語言的方式使用range()
,以表示實數線的連續段,如4.5到5.25所示 。 但是range()
在Python中並不意味着那樣。 這意味着一堆整數。 因此,即使在指定范圍內 ,浮點值也不會出現在range()
函數生成的一堆整數中。
你的第一個測試是
if n in range( int(1e-12),int(9e-11)):
我猜你是這樣寫的,因為你真正想要的是range(1e-12, 9e-11)
但是你得到TypeError: 'float' object cannot be interpreted as an integer
。
但是,如果您在解釋器提示下執行此操作
>>> range(int(1e-12),int(9e-11))
range(0, 0)
>>> list(range(int(1e-12),int(9e-11)))
[]
您會看到它意味着與您明顯期望的完全不同的東西。
要測試浮點數是否在給定范圍內,請執行
if lower-bound <= mynumber <= upper-bound:
您不需要范圍,並且如果您基於固定閾值的定界點來界定單位幅度,則邏輯將更加強大。 在給定的比例下,這通常是一個單位。
這是確定所有單位比例的通用方法:
SI_Length = [ (1/1000000000000,"pm"),
(1/1000000000, "nm"),
(1/1000000, "um"),
(1/1000, "mm"),
(1/100, "cm"),
(1, "m"),
(1000, "km") ]
SI_Frequency = [ (1, "Hz"), (1000,"kHz"), (1000000,"MHz"), (1000000000,"GHz")]
def convert(n,units):
useFactor,useName = units[0]
for factor,name in units:
if n >= factor : useFactor,useName = factor,name
return (n/useFactor,useName)
print(convert(0.0035,SI_Length)) # 3.5 mm
print(convert(12332.55,SI_Frequency)) # 12.33255 kHz
每個單位數組必須按最小到最大的倍數順序排列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.