将整数值转换为浮点值,步长取决于范围

2024-09-27 09:26:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个滑块,我用它来改变一个参数(y),这个参数的值范围很广。滑块的位置以整数形式给出(x)。你知道吗

我的参数保存一个源的能量,并且可以有从0.1 nJ到10 J的值。出于应用目的,我希望参数步长为:

  • 0.1 nJ英寸[0.1 nJ-1.0µJ]
  • 0.1µJ英寸[1.0µJ-1.0兆焦耳]
  • 0.1兆焦耳英寸[1.0兆焦耳-1.0兆焦耳]
  • 0.1 J英寸[1.0 J-10.0 J]

我试图通过使用整数除法(//)和余数(%)操作来转换这些值(x => y),但是当我从一个子范围转换到另一个子范围时遇到了问题,例如。你知道吗

x=9999得到y=999.9 nJ,这是应该的,但是x=10000得到y=0.0µJ,这在系统中是0,远低于999.9 nJ。下一步(x=10001)得到y=0.1µJ,也低于999.9 nJ。你知道吗

理想情况下,y的步长应为999.9 nJ-1.0µJ-1.1µJ

这个MWE使用key detection读取键的输入,而不必按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.9nj,因为这是出错的地方。你知道吗

我知道用我正在使用的算法将x=10001转换为0.1µJ是合乎逻辑的,但我不知道如何解决它。如果您只能用+-按钮更改值,则可以直接从9999更改为10011,这在逻辑上会给出y=1.1µJ,但是如何处理实际滑块可以用鼠标拖动的事实呢?你知道吗

请告诉我你对如何解决这个问题有什么想法。你知道吗


Tags: ofthefromfor参数timevaluesys
2条回答

在每个半开间隔中有9999个值,在最后一个闭合间隔中有90个值,因为(例如)10000(0.1 nJ)=1µJ。这使得转换很容易:

def val(x):   # 0<=x<30,087
  r,x=divmod(x,9999)
  return (x+1)*1000**(r-3)/10

(注释中有一些关于扩展以支持其他范围的内容,但不够具体,无法回答。)

感谢@Davis Herring的评论和建议,我想我已经解决了这个问题。该函数现在可以根据不同的分辨率(步长)和起始指数(exp0)进行调整。你知道吗

def calcy(x):
    if x < (1000*resolution - 1):        # The number of values from the start to the first prefix change
        exp = exp0
        yp = round((x + 1)/resolution, digits) # Round to account for numerical discrepancies
    else:
        n = round((1000 - 1) * resolution) # The number of values in all other ranges
        z = round(x - (1000 * resolution - 1)) # Subtract the number of values in the first range
        r = z // n + 1          # The number of passed ranges
        yp = round((z % n)/resolution + 1, digits)
        exp = exp0 + 3 * r
    return yp * 10**exp

使用resolution = 10digits = 1时,第一个范围内的每一步都是0.1 nJ,然后是0.1µJ,0.1mJ。。。。。。你知道吗

相关问题 更多 >

    热门问题