如何提取浮点数的分子、分母和根


FLOAT_NUM = 2*math.sqrt(3)/5
>>> 0.23094010767585033

考虑到我从FLOAT_NUM的值开始,如何提取分子==2和分母==5以及uder根==3的值?例如:

input >> 0.23094010767585033
output>> 2,5,3

虽然不可能找到反向操作,因为可以从多个操作中获得相同的值:

def f(a,b,c):
return a*np.sqrt(b)/c
f(1,1,1) == f(2,1,2) 

你肯定可以找到一组产生输出的值(通过更改初始猜测x0,你可以控制它应该搜索的"值的区域",你可以添加约束等,只需查看scipy的文档(

import numpy as np
from scipy.optimize import minimize
def f(a,b,c):
return a*np.sqrt(np.abs(b))/c # for safety we remove sign from b
def loss(x, value):
return (f(*x)-value)**2

print(minimize(loss, x0=(1,1,1), args=( 0.23094010767585033,)))

输出

fun: 1.407352885154195e-12
hess_inv: array([[2.19894411, 0.10853698, 0.53500981],
[0.10853698, 0.97322067, 0.16951733],
[0.53500981, 0.16951733, 0.81315655]])
jac: array([ 1.15720094e-06,  4.00176469e-07, -3.21558937e-07])
message: 'Optimization terminated successfully.'
nfev: 20
nit: 4
njev: 5
status: 0
success: True
x: array([0.47495072, 0.68534754, 1.70255982])

因此,对于a=0.47495072,b=0.68534754,c=1.70255982,您将获得几乎感兴趣的值(最多1e-12错误(。

现在,如果a、b和c应该是整数,事情会变得更加棘手。你仍然可以通过优化的路径-简单地用任何遗传算法库或其他无梯度优化器取代scipy。

一个非常粗略的整数版本使用盆地跳跃:

import numpy as np
from scipy.optimize import basinhopping
def f(a,b,c):
return int(a)*np.sqrt(int(np.abs(b)))/int(c)
def loss(x, value=0.23094010767585033):
return (f(*x)-value)**2
r=basinhopping(loss, stepsize=1, niter=10000, x0=(1,1,1), )
print(r)
print(list(map(int, r['x'])))

以及示例性输出

fun: 7.703719777548943e-34
lowest_optimization_result:       fun: 7.703719777548943e-34
hess_inv: array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
jac: array([0., 0., 0.])
message: 'Optimization terminated successfully.'
nfev: 4
nit: 0
njev: 1
status: 0
success: True
x: array([ 2.69160446,  3.44627592, 15.48606124])
message: ['requested number of basinhopping iterations completed successfully']
minimization_failures: 5
nfev: 40004
nit: 10000
njev: 10001
x: array([ 2.69160446,  3.44627592, 15.48606124])
[2, 3, 15]

显示2*sqrt(3(/15会给出您所需的值,最大错误为1e-34。

由于存在无限的可能性,这里有一个函数将返回其中一个。

def lazy_solution(float_num):
numerator = str(float_num)[2:]
denominator = '1' + '0'*(len(numerator) - 1)
root = 1
return int(numerator), root, int(denominator)

最新更新