У меня есть ползунок, который я использую для изменения параметра (y
), который может иметь широкий диапазон значений.Положение ползунка задается как целое число (x
).
Мой параметр содержит энергию источника и может иметь значения от 0,1 нДж до 10 Дж. Для целей применения Iразмер шага параметра должен быть:
- 0,1 нДж в [0,1 нДж - 1,0 мкДж]
- 0,1 мкДж в [1,0 мкДж - 1,0 мДж]
- 0,1 мДж в [1,0 мДж - 1,0 Дж]
- 0,1 Дж в [1,0 Дж - 10,0 Дж]
Я пытаюсь преобразовать эти значения (x => y
) с помощьюоперации целочисленного деления (//
) и остатка (%
), но я сталкиваюсь с проблемами, например, при переходе из одного поддиапазона в другой.
x = 9999 дает y =999,9 нДж, что и должно, но тогда x = 10000 дает y = 0,0 мкДж, что в системе равно 0 и намного ниже, чем 999,9 нДж.Следующий шаг (x = 10001) дает y = 0,1 мкДж, что также ниже, чем 999,9 нДж.
В идеале шаги y должны составлять 999,9 нДж - 1,0 мкДж - 1,1 мкДж.
ЭтоMWE использует обнаружение клавиш для считывания ввода клавиш без необходимости нажатия клавиши ENTER.
import math as m
import sys, termios, tty, os, time
prefixes = {-18:'a', -15:'f', -12:'p', -9:'n', # Prefixes for displaying the value
-6:'\u03bc', -3:'m', #-2:'c', -1:'d',
+0:'', #+1:'da', +2:'h',
+3:'k', +6:'M', +9:'G', +12:'T', +15:'P', +18:'E'}
def getch(): # Get character from keyboard without waiting for enter
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def calcy(): # Convert from x integer to y value for display
print("x: " + repr(x))
exp2 = 3*((x/resolution) // 1e+3) + exp0 # integer division
yp2 = round((x/resolution)%(1e+3), digits) # remainder
y2 = round(yp2 * m.pow(10, exp2), int(digits-exp2))
print("y: " + repr(y2) + " equal to " + repr(yp2) + str(prefixes[exp2]) + "J\n")
button_delay = 0.1
y = float(input("Give starting value:")) # Choose a value to start from
exp0 = -9 # Exponent of minimum range [nJ]
digits = 1 # Number of decimals to be used
resolution = m.pow(10, 1) # The number of points for a change of size 1
exp = 0 # Exponent of y
yp = y # Short number of y
while yp < 1/resolution: # While the number is not in the prefixed unit
yp = yp*1e+03 # Multiply yp by 1000 (10³)
exp -= 3 # Exponent increases by 3
yp = round(y * m.pow(10, -exp), digits) # The display value
x = int((yp + (exp - exp0)/3 * 1e+3) * resolution) # Integer value representing the silder value
calcy() # Calculate y from x integer
while True:
char = getch() # Get pressed key
if char == 'q': # If it was q, quit
exit(0)
elif char == '+': # If it was +, increase x by one and
x += 1 # recalculate y
calcy()
time.sleep(button_delay)
elif char == '-': # If it was -, decrease x by one and
x -= 1 # recalculate y
calcy()
time.sleep(button_delay)
else:
print(char)
time.sleep(button_delay)
Если вы хотите попробовать эту программу, я рекомендую указать 500e-9
в качестве начального значения инажимая -
6 раз, чтобы получить y = 999,9 нДж, потому что здесь все идет не так.
Я понимаю, что логично для x = 10001 преобразовать в 0,1 мкДж с помощью алгоритма, который я использую, но я нене знаю, как это решить.Если бы вы могли изменить значение только с помощью кнопок +
и -
, можно было бы перейти непосредственно с 9999 на 10011, что логически дало бы y = 1,1 мкДж, но как бы я тогда справился с тем фактом, что фактический слайдер можно перетаскиватьс помощью мыши?
Пожалуйста, дайте мне какие-нибудь идеи, как решить эту проблему.