简体   繁体   中英

how to extract numerator and denominator and root of a float number?

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

considering i started with FLOAT_NUM's value how to extract numerator==2 and denominator==5 and the value uder root==3? for example:

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

While it is impossible to find a reverse operation, as the same value can be obtained from multiple ones:

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

f(1,1,1) == f(2,1,2) 

you can definitely find a set of values that produces your output (and by changing initial guess x0 you can control "what region of values" it should search for, you can add constraints etc., just look at documentation of 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,)))

Outputs

      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])

Thus for a=0.47495072, b=0.68534754, c=1.70255982 you will get almost the value of interest (up to 1e-12 error).

Now things will get a bit more tricky if a, b and c are supposed to be integers. You can still go through the path of optimisation - simply replace scipy with any library for genetic algorithm or other gradient-free optimiser.

A very rough integer version using basin hopping:

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'])))

and an exemplary output

                        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]

Showing that 2*sqrt(3)/15 gives your desired value up to 1e-34 error.

Since there are infinite possibilities, here is a function which will return one of them.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM