假设你有一个任意值V
,并且你知道0 <= V
<= Vmax
。你想计算像素的x坐标,称之为X
,其中你的“屏幕”具有从0到Xmax
的x坐标。如你所说,要以“正常”的方式做到这一点,你需要执行:
X = Xmax * V / Vmax
V = Vmax * X / Xmax
我喜欢把它想象成首先通过计算 V/Vmax
来将值标准化为介于0和1之间的值,然后将此值乘以最大值以获得介于0和该最大值之间的值。
要以对数方式进行相同的操作,需要使用不同的下限值来处理 V
值。如果 V 小于等于 0,则会出现 ValueError
。 因此,假设 0 Vmin
<= V
<= Vmax
。 然后你需要找到使用哪个对数,因为有无限多个对数可以使用。 其中三个常见的对数是以2、e和10为底数的,这将导致 x 轴看起来像这样:
------|------|------|------|---- ------|------|------|------|----
2^-1 2^0 2^1 2^2 == 0.5 1 2 4
------|------|------|------|---- ------|------|------|------|----
e^-1 e^0 e^1 e^2 == 0.4 1 2.7 7.4
------|------|------|------|---- ------|------|------|------|----
10^-1 10^0 10^1 10^2 == 0.1 1 10 100
原则上,如果我们可以从左侧的表达式中获取幂指数,我们就可以使用与上面相同的原理来获取介于0和Xmax
之间的值,这当然涉及到对数。假设您使用基数b
,您可以使用这些表达式进行转换:
from math import log
logmax = log(Vmax / Vmin, b)
X = Xmax * log(V / Vmin, b) / logmax
V = Vmin * b ** (logmax * X / Xmax)
思路几乎相同,唯一不同的是你需要先确保log(somevalue, b)
能得到非负值。这可以通过在log
函数内部除以Vmin
来实现。现在您可以除以表达式可能产生的最大值,当然这个最大值是log(Vmax / Vmin, b)
,您将得到一个介于0和1之间的值,与之前一样。
另一种方法是首先归一化(X / Xmax
),然后再缩放(* logmax
)到逆函数所期望的最大值。顺便说一下,逆函数是将b
升至某个值。现在,如果X
为0,b ** (logmax * X / Xmax)
将等于1,因此要获得正确的下限,我们需要乘以Vmin
。换句话说,由于我们从另一个方向开始时做的第一件事是除以Vmin
,因此现在我们需要在最后一步乘以Vmin
。
要“放大”方程式的“右侧”,您只需切换方程式,使其自V
到X
进行指数运算,并在另一侧进行对数运算。原则上,是这样的。因为您还必须处理X
可能为0的情况:
logmax = log(Xmax + 1, b)
X = b ** (logmax * (V - Vmin) / (Vmax - Vmin)) - 1
V = (Vmax - Vmin) * log(X + 1, b) / logmax + Vmin
max
非常小的值? - Paulo Scardine(X/max)*V
,更易读为X * V/max
。 - wim