问题
Given values for the variables s
, v
, and h
, and given a library such as numeric.js how can I numerically solve the following equation for a
within a given degree of accuracy?
I'm wanting a JS algorithm for use in-browser.
回答1:
Separating variables and parameters
You could start by substituting b = a/h. That would turn your equation into
2b*sinh(1/(2b)) = sqrt(s²-v²)/h
That way you have all the inputs on the right hand side, and the variable on the left hand side, but unfortunately still occuring in several places in a transcendental form. The benefit is that we can now treat the right-hand side as a single number in order to gain some understanding of this function.
First look at a plot
The function seems reasonably well-behaved:
So you can do standard numerical root-finding methods, e.g. Newton's method, to find the position where this function takes a given value (i.e. the one you computed from the right-hand side). If you interpret root-finding as finding locations where a function is zero, then the function for which you want to find zeros is the difference, i.e.
2a*sinh(h/(2a)) - sqrt(s²-v²)
Using optimization from numeric.js
If you want to make use of numeric.js, numeric.uncmin
would likely be your best bet. At least it's the best I could find in the docs so far. (Perhaps there is some bare root-finding implementation in there, but if so, I couldn't find it yet.) You'd try to find the minimum of the function
(2a*sinh(h/(2a)) - sqrt(s²-v²))²
interpreted as a function of a, and hope that that minimum is actually (close to) zero. You might get better results (i.e. faster convergence and/or lower error) by also providing the gradient (derivative) of that function as a separate argument. You can use Wolfram Alpha to find that derivative.
Further rewriting of the function
Let's define f as f(b) = 2b*sinh(1/(2b)). You are trying to find out at what position f assumes a given value. In order to make convergence faster, you can try to turn this f into a different function which will be close to linear. Toying around with plots, I've come up with this:
g(b) = (f(b) - 1)^(-1/2)
You can apply the same conversion to the right hand side to see the desired value for this function. For b > 0.06 this looks fairly linear, so it should converge really fast. Provided your parameters are expected to be in that range where it is almost linear, but even for smaller b it should be no worse than the original formulation. You could use the linear form to compute the starting position of your Newton's method, but I wouldn't bother: as long as you start with a reasonably big value, the first step of Newton's method will do just that.
回答2:
this is transcendent equation
I assume real domain in that case you can not separate the unknown from it (in general) instead you still can solve it numerically (as you intended)
I am too lazy to do proper analysis of
2a.sinh(h/2a)=sqrt(s.s-v.v)
but if I see it right then
2a.sinh(h/2a)
is monotone so letc=sqrt(s.s-v.v)
for simplicity and speed up. As I see itc >= 0
so ifh >= 0
thena = <0,+inf)
find value crossing
double a0,a1,da=initial accuracy step; for (a1=0.0;2a.sinh(h/2a)<=sqrt(s.s-v.v);a1+=da);
now
a1
holds approximate top bound solutionfor (a0=a1;2a.sinh(h/2a)>sqrt(s.s-v.v);a0-=da);
now
a0
holds approximate low bound solutionfind solution in desired accuracy
ifa0==a1
then you have found exact solution so stop
iffabs(a1-a0)<=accuracy
you are inside your accuracy so stop and lower theda
for exampleda*=0.01;
this will boost accuracy100
times. Now search for solution again but only on interval<a0,a1>
and repeat this until solution is found
[notes]
Another example of solution of transcendent equation is here: solving Kepler`s equation. When nothing else works you still can try this:
- How approximation search works
来源:https://stackoverflow.com/questions/25753546/solving-a-trig-equation-numerically-with-in-browser-js