我想在python中找到N / 2 ** M形式的浮点数的最接近表示,其中N和M是整数。我试图使用scipy.optimise中的最小化函数,但它不能局限于N和M是整数的情况。
我最终使用了一个简单的实现,它迭代M和N的值并找到最小值,但这对于许多数组来说计算成本高且耗时,这可能是更好的方法吗?
我的简单实现如下所示:
import numpy as np
def ValueRepresentation(X):
M, Dp = X
return M/(2**Dp)
def Diff(X, value):
return abs(ValueRepresentation(X) - value)
def BestApprox(value):
mindiff = 1000000000
for i in np.arange(0, 1000, 1):
for j in np.arange(0, 60, 1):
diff = Diff([i, j], value)
if diff < mindiff:
mindiff = diff
M = i
Dp = j
return M, Dp
答案 0 :(得分:2)
只需使用内置功能:
In [10]: 2.5.as_integer_ratio() # get representation as fraction
Out[10]: (5, 2)
In [11]: (2).bit_length() - 1 # convert 2**M to M
Out[11]: 1
请注意,所有非无限的非NaN浮点数都是二元有理数,因此我们可以依赖分母为2的精确幂。
答案 1 :(得分:0)
感谢jasonharper,我意识到我的实现效率低得离谱,而且可能更简单。
他的方法的实现如下所示:
def BestApprox_fast(value):
mindiff = 1000000000
for Dp in np.arange(0, 32, 1):
M = round(value*2**Dp)
if abs(M) < 1000:
diff = Diff([M, Dp], value)
if diff < mindiff:
mindiff = diff
M_best = M
Dp_best = Dp
return M_best, Dp_best
大约快200倍。
答案 2 :(得分:0)
对M和N给出限制,N / 2 ** M的范围是一个明确定义的离散数字刻度:
[0-1000 / 2 ^ 26,501-1000 / 2 ^ 25,501-1000 / 2 ^ 24,... 501-1000 / 2 ^ 1,501-1000 / 2 ^ 0]。
在这个给定的离散集中,不同的子集具有不同的准确度/分辨率。第一个子集[0-1000 / 2 ^ 26]具有2 ^ -26或26个二进制位分辨率的精度。因此,只要给定的数字落在相应的连续域[0,1000 / 2 ^ 26]中,可实现的最佳精度为2 ^ -26。接着,当给定数量超出第一个域但落入域[500/2 ^ 25,1000 / 2 ^ 25]时,最佳准确度为2 ^ 25,这对应于第二个子集[501-1000 / 2 ^ 25] ]。 (注意离散集和连续域之间的区别。)
根据上述逻辑,我们知道由M定义的最佳准确度取决于给定数字在比例上的位置。因此我们可以按照以下python代码实现它:
import numpy as np
limits = 1000.0/2**np.arange(0,61)
a = 103.23 # test value
for i in range(60,-1,-1):
if a <= limits[i]:
N = i
M = round(a * 2**N)
r = [M, N]
break
if a > 1000:
r = [round(a), 0]
此解决方案具有O(c)执行时间,因此非常适合多次调用。