Approximate arcsinc

The goal is simple: Output a nonzero real solution x to the equation sin(x) = -mx, given input m, in the fewest number of bytes.

Specifications:

• Your answer must be correct to 3 significant figures.
• You may output any real solution other than the trivial solution x=0. You can assume m is such that at least one solution exists. You may also assume m!=0.

An obviously suboptimal python solution using gradient descent:

from math import *
from random import *
a=x=0.001
m = 5.
def dE(x):return 2*(sin(x)+m*x+1)*(cos(x)+m)
for i in xrange(1000): x-=dE(x)*a
print x

Test cases

-0.25 -> ±2.4746
-0.1  -> ±2.8523 or ±7.0682 or ±8.4232
0.2  -> ±4.1046 or ±4.9063
• The best approach here is to print a fixed value, though you should specify how many decimal places are required. I'd suggest including an input parameter, like a to solve sin(x)=-ax. Please don't say "you have to actually compute it", since requirements like that are too vague to work. – xnor Oct 27 '16 at 5:09
• Also, x=0 is a trivial solution. You should specify which solution you want. – xnor Oct 27 '16 at 5:10
• You need some bounds on m to guarantee a nonzero solution. – xnor Oct 27 '16 at 5:23
• m=0 has solutions (x=kπ for integer k). The values of m which don't have non-trivial real solutions are those which are too far from 0. – Peter Taylor Oct 27 '16 at 5:54
• Are you looking for only real-valued solutions or are complex-valued solutions allowed too? – miles Oct 27 '16 at 6:03

ised: 32 28 bytes

Using Newton's iteration starting from π:

{:x-{sinx+$1*x}/{cosx+$1}:}:::pi

The argument is passed in $1, which can be taken from a file, like this: ised --l inputfile.txt 'code' A bit less stable, but shorter version: {:{x-tanx}/{1+$1/cosx}:}:::pi

Sometimes it throws iteration limit warnings but the accuracy seems fine considering the conditions.

Unicode version (same bytecount):

{λ{x-tanx}/{1+$1/cosx}}∙π Starting from 4 cuts another byte and seems to converge to the same values {λ{x-tanx}/{1+$1/cosx}}∙4

f m=until(\x->sin x< -m*x)(+1e-3)0

Counts x up from 0 by 0.001 until sin(x)< -m*x.

Ouput examples

f -0.2 ->   2.595999999999825
f -0.1 ->   2.852999999999797
f  0.0 ->   3.141999999999765
f  0.1 ->   3.4999999999997256
f  0.2 ->   4.1049999999997056
• What about m=-0.1? – Peter Taylor Oct 27 '16 at 5:55
• @PeterTaylor Note sure if it's required, but it gives 2.853, which looks right. – xnor Oct 27 '16 at 6:00
• Of course, they're both odd functions so if there's a solution there's a positive solution. Doh. – Peter Taylor Oct 27 '16 at 6:05
• Why would you answer a challenge that you know is unclear? – Mego Oct 27 '16 at 6:19

Mathematica, 28 bytes

x/.FindRoot[Sinc@x+#,{x,1}]&

Searches for a numerical root from the initial guess x=1. Test cases:

% /@ {-0.25, -0.1, 0.2}
(* {2.47458, 2.85234, 4.10462} *)

C, 99 bytes

#include<math.h>
float f(float m){float x=1,y;do{x=(y=sin(x)+m*x)+x;}while(fabs(y)>1e-4);return x;}

ungolfed:

#include<math.h>
float f(float m){
float x=1,y;
do{x=(y=sin(x)+m*x)+x;}while(fabs(y)>1e-4);
return x;
}

MATL, 17 bytes

@2e3/tY,wG_*>}4M

This uses linear search on the positive real axis, so it is slow. All test cases end within 1 minute in the online compiler.

Try it online!

Explanation

% Do...while
@       %   Push iteration index, starting at 1
2e3/    %   Divide by 2000
t       %   Duplicate
Y,      %   Sine
w       %   Swap
G_*     %   Multiply by minus the input
>       %   Does the sine exceed that? If so, next iteration
}         % Finally (execute after last iteration, before exiting loop)
4M     %   Push input of sine function again
% Implicit end
% Implicit display

C++ 11, 92 91 bytes

-1 byte for using #import

#import<cmath>
using F=float;F f(F m,F x=1){F y=sin(x)+m*x;return fabs(y)>1e-4?f(m,x+y):x;}

Python 2, 81 78 bytes

Fixpoint iteration

As recursive lambda

from math import*
f=lambda m,x=1:abs(sin(x)+m*x)>1e-4and f(m,sin(x)+m*x+x)or x

As loop (81 bytes):

from math import*
m=input()
x=1
while abs(sin(x)+m*x)>1e-4:x=sin(x)+m*x+x
print x

Mathematica, 52 bytes

NSolve[Sin@x==-x#,x,Reals][[;;,1,2]]~DeleteCases~0.&

Anonymous function. Takes a number as input, and returns a list of numbers as output. Just uses NSolve to solve the approximate equation.

• If you replace Sin@x==-x# with Sinc@x==-# you can do away with ~DeleteCases~0. – lastresort Oct 27 '16 at 13:29

Axiom, 364 bytes

bisezione(f,a,b)==(fa:=f(a);fb:=f(b);a>b or fa*fb>0=>"fail";e:=1/(10**(digits()-3));x1:=a;v:=x2:=b;i:=1;y:=f(v);if(abs(y)>e)then repeat(t:=(x2-x1)/2.0;v:=x1+t;y:=f(v);i:=i+1;if i>999 or t<=e or abs(y)<e then break;if fb*y<0 then(x1:=v;fa:=y)else if fa*y<0 then(x2:=v;fb:=y)else break);i>999 or abs(y)>e=>"fail";v)
macro g(m) == bisezione(x+->(sin(x)+m*x), 0.1, 4.3)

ungolf

bisezione(f,a,b)==
fa:=f(a);fb:=f(b)
a>b or fa*fb>0=>"fail"
e:=1/(10**(digits()-3))
x1:=a;v:=x2:=b;i:=1;y:=f(v)
if(abs(y)>e) then
repeat
t:=(x2-x1)/2.0;v:=x1+t;y:=f(v);i:=i+1
if i>999 or t<=e or abs(y)<e then break
if      fb*y<0 then(x1:=v;fa:=y)
else if fa*y<0 then(x2:=v;fb:=y)
else break
i>999 or abs(y)>e=>"fail"
v

macro g(m) == bisezione(x+->(sin(x)+m*x), 0.1, 4.3)

results

(3) -> g(0.2)
AXIOM will attempt to step through and interpret the code.
(3)  4.1046198505 579058527
Type: Float
(4) -> g(-0.1)
(4)  2.8523418944 500916556
Type: Float
(5) -> g(-0.25)
(5)  2.4745767873 698290098
Type: Float