Here is a function to approximate log10(x+1) for (x+1) < ~1.2:
a = 1.097
b = 0.085
c = 2.31
ans = 1 / (a - b*x + c/x)
It should look like that:
It works by adjusting harmonic mean to match log10, but the problem is in values of a, b, c.
The question is how to get just right a, b and c and how to make better approximation.
I made this code that can give a pretty good approximation for a, b, c, but my code wasn't able to make it any better.
import numpy as np
a = 1
b = 0.01
c = 2
def mlg(t):
x = t
if t == 0:
x = 0.00000001
x2 = x*x
o = a - (b * x) + (c / x)
return 1/o
def mlg0(t):
x = t
if t == 0:
x = 0.00000001
x2 = x*x
o = a - (b * x) + (c / x)
return o
for i in range(9000):
n1 = np.random.uniform(0,1.19,1000)
for i in range(1000):
n = n1[i]
o = np.log10(n+1)
u = mlg(n) - o
e = u ** 2
de_da = 0 - 2 * (u) / (mlg0(n) ** 2)
de_db = de_da * n
de_dc = de_da / n
a -= de_da * 0.00001
b -= de_db * 0.00001
c -= de_dc * 0.00001
print(a,b,c)
How could the code be changed to generate better values?
I've used a method alike back propagation in NN, but it could not give me values any better.
Here is how the error is calculated:
Here are two approaches.
Method 1: series expansion in x (better for negative and positive x)
Method 2: fit the curve that passes through 3 points (here, x=0, ½ and 1)
Method 1.
If you expand them by Taylor series as powers of x then
Equating coefficients of x, x^2 and x^3 gives
In code:
import math
import numpy as np
import matplotlib.pyplot as plt
c = math.log( 10 )
a = c / 2
b = c / 12
print( "a, b, c = ", a, b, c )
x = np.linspace( -0.2, 0.2, 50 )
y = np.log10( 1 + x )
fit = x / ( a * x - b * x ** 2 + c )
plt.plot( x, y , 'b-', label="Original" )
plt.plot( x, fit, 'ro', label="Fit" )
plt.legend()
plt.show()
Output:
a, b, c = 1.151292546497023 0.19188209108283716 2.302585092994046
Method 2.
Fit to three points. Here we require
If we require this to fit at x=0, ½ and 1 we get (including L’Hopital’s rule for the limit at x=0)
This time I have used your interval x in [0,1] to plot the fit
import math
import numpy as np
import matplotlib.pyplot as plt
c = math.log( 10 )
a = c * ( 2/math.log(1.5) - 1/math.log(2) - 3 )
b = 2 * c * ( 1/math.log(1.5) - 1/math.log(2) - 1 )
print( "a, b, c = ", a, b, c )
x = np.linspace( 0.0, 1.0, 50 )
y = np.log10( 1 + x )
fit = x / ( a * x - b * x ** 2 + c )
plt.plot( x, y , 'b-', label="Original" )
plt.plot( x, fit, 'ro', label="Fit" )
plt.legend()
plt.show()
Output:
a, b, c = 1.1280638006656465 0.1087207987723298 2.302585092994046