Python внутренняя метрическая функция преобразования единиц - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь создать функцию для внутреннего преобразования метрики в программе преобразования длины волны в частоту, и мне было трудно заставить ее работать должным образом.Он очень медленный и не назначит правильные метки на выход.Если кто-то может помочь с другим методом вычисления этого или с причиной, по которой это происходит, и с любыми исправлениями, которые я могу сделать, это было бы удивительно!

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))

Ответы [ 3 ]

0 голосов
/ 19 февраля 2019

Вы используете 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:
0 голосов
/ 19 февраля 2019

Вам не нужны диапазоны, и ваша логика будет более устойчивой, если вы будете основывать ее на фиксированных пороговых точках, которые ограничивают единицу измерения.Обычно это будет единица в данном масштабе.

Вот обобщенный подход к определению масштаба всех единиц:

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

Каждый массив единиц должен быть в порядке наименьшего к наибольшему множителю.

0 голосов
/ 19 февраля 2019

РЕДАКТИРОВАТЬ: На самом деле, 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 работает только с целыми числами, а не с плавающей точкой.

Больше EDIT:

Для вашего конкретного случая использованияВы можете определить словарь пар * (значение, символ), как показано ниже:

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

Вы можете адаптировать эту функцию к вашим потребностям ...

...