How to find number of common decimal digits of two arrays element wise?
Question:
I have a complex function I want to approximate, and I use np.polyfit
to find the polynomial to approximate it.
And I want to find the statistics of correct decimal places to determine the quality of the approximation.
But it is hard to do efficiently. Currently I just convert the elements to strings and find the longest common prefix length element by element, needless to say this is inefficient.
import numpy as np
from collections import Counter
x = np.linspace(1, 2, 4096)
exp = np.exp(x)
poly = np.polyfit(x, exp, 6)
approx = np.polyval(poly, x)
def LCP(s1, s2):
c = 0
for a, b in zip(s1, s2):
if a != b:
break
c += 1
return c
def leading_digits(f1, f2):
l = LCP(str(f1), str(f2)) - 1
return max(l, 0)
correct_places = Counter()
for a, b in zip(approx, exp):
correct_places[leading_digits(a, b)] += 1
Counter({7: 2014, 8: 1699, 6: 207, 9: 135, 5: 27, 10: 12, 11: 2})
What is a more efficient way?
Answers:
So I’m not exactly sure why you’re wanting to compare digits for accuracy, there are a lot of other well known stats to determine the efficacy of an approximation. I would start with r-squared. If you do want to compare digits you could do something like the following:
a = 10.1234567891
b = 10.1234567890
c = a-b
digits = 0
while c < 1:
digits += 1
c *= 10
print(digits)
# digits = 10
digits
would be how many decimal places they have in common
Comparing the number of equal leading digits doesn’t seem like a good approach. 1.01
and 1.09
have 2
leading digits in common, 1.09
and 1.10
only 1
, but the second pair has a smaller absolute difference.
I would compute the absolute difference and get the order of magnitude of it using logarithms:
diff = abs(approx-exp)
Counter(-np.floor(np.where(diff>0, np.log10(diff), 0)).astype(int))
Output:
Counter({8: 3488, 7: 307, 9: 272, 10: 26, 11: 2, 12: 1})
I have a complex function I want to approximate, and I use np.polyfit
to find the polynomial to approximate it.
And I want to find the statistics of correct decimal places to determine the quality of the approximation.
But it is hard to do efficiently. Currently I just convert the elements to strings and find the longest common prefix length element by element, needless to say this is inefficient.
import numpy as np
from collections import Counter
x = np.linspace(1, 2, 4096)
exp = np.exp(x)
poly = np.polyfit(x, exp, 6)
approx = np.polyval(poly, x)
def LCP(s1, s2):
c = 0
for a, b in zip(s1, s2):
if a != b:
break
c += 1
return c
def leading_digits(f1, f2):
l = LCP(str(f1), str(f2)) - 1
return max(l, 0)
correct_places = Counter()
for a, b in zip(approx, exp):
correct_places[leading_digits(a, b)] += 1
Counter({7: 2014, 8: 1699, 6: 207, 9: 135, 5: 27, 10: 12, 11: 2})
What is a more efficient way?
So I’m not exactly sure why you’re wanting to compare digits for accuracy, there are a lot of other well known stats to determine the efficacy of an approximation. I would start with r-squared. If you do want to compare digits you could do something like the following:
a = 10.1234567891
b = 10.1234567890
c = a-b
digits = 0
while c < 1:
digits += 1
c *= 10
print(digits)
# digits = 10
digits
would be how many decimal places they have in common
Comparing the number of equal leading digits doesn’t seem like a good approach. 1.01
and 1.09
have 2
leading digits in common, 1.09
and 1.10
only 1
, but the second pair has a smaller absolute difference.
I would compute the absolute difference and get the order of magnitude of it using logarithms:
diff = abs(approx-exp)
Counter(-np.floor(np.where(diff>0, np.log10(diff), 0)).astype(int))
Output:
Counter({8: 3488, 7: 307, 9: 272, 10: 26, 11: 2, 12: 1})