如何解决这个问题:两个函数x = sin(x)/ a

时间:2014-03-12 19:38:48

标签: c math binary-search

我试图用不同的方式解决这个等式,但没有运气:

找到两个函数的点数。

f(x) = sin(x)  
y = a  

在给定的a。在这种情况下,我们可以说a = 0.15

sin(x) = ax
= 0.15x
x = sin(x)/0.15

???

任何人都可以帮助解决这个问题吗?

这就是确切的问题:

编写一个读取值a的C程序,并写出等式sin(x) = a*x

的所有解(即根)

注意:此等式肯定有一个解决方案:x = 0。然而,对于a的低值,表示等式y = a*x的线足够接近水平线以多次穿过正弦波。您的程序应计算并打印根数及其值。

提示:假设您要求解等式f(x) = 0,其中f(x)是连续函数。进一步假设您可以找到两个值xlowxhigh,以便f(xlow) < 0f(xhigh) > 0和函数f(x)仅在这些值之间穿过x轴一次值。您可以继续使用所谓的“二进制搜索”技术,如下所示:

  
      
  1. 将解x估计为x =(xlow + xhigh)/ 2.0
  2.   
  3. 如果| f(x)| &LT; epsilon然后打印x作为解决方案并退出;其他
  4.   
  5. 如果f(x)< 0然后替换xlow = x else替换xhigh = x
  6.   
  7. 转到(1)
  8.   

使用epsilon = 0.001

3 个答案:

答案 0 :(得分:1)

  

您可以继续使用所谓的“二元搜索”技术

这是解决方案的关键。实际上它的解决方案。让我画两个函数:

           f(x)   g(x)
            /    --
           /   --
          /  --
         / --
        /--
       -*
     --/
   -- /
 --  /

 ^                 ^
 |                 |
 xlow              xhigh

您有xlowxhigh作为f(x)越过g(x)的估算值。在您的问题中,f(x) = axg(x) = sin(x)

首先,让我们看看为什么xlowxhigh做出了很好的估计。如果您注意到,我们xlowf(x) < g(x)xhigh f(x) > g(x)我们f(x) == g(x)。由于函数是连续的,因此在xlow之间的某处有一点。

现在让我们看一下xhigh f(x) g(x) / -- / -- / -- / -- /-- -* --/ -- / -- / ^ ^ ^ | | | xlow xmid xhigh 之间的中间点:

xmid

现在在f(x) > g(x),我们有f(xhigh) > g(xhigh) f(xmid) > g(xmid) f(xlow) < g(xlow) (在此示例中)。所以:

xmid

xlowf(x) - g(x)之间,函数变更大 - 船(换句话说,xlow更改其符号),然后答案肯定在{{1}之间}和xmid(请注意xmidxhigh之间仍然可能存在偶数个解,但我们现在还不能说明。)

因此,如果我们分配xhigh = xmid,我们会:

       f(x)  g(x)
         /--
       -*
     --/
   -- /
 --  /

 ^        ^
 |        |
 xlow     xhigh

但这和以前一样!除了我们将解决方案的可能位置缩小一半。重复我们:

       f(x)  g(x)
         /--
       -*
     --/
   -- /
 --  /

 ^    ^    ^
 |    |    |
 xlow xmid xhigh

f(xhigh) < g(xhigh)
f(xmid)  > g(xmid)
f(xlow)  > g(xlow)

这一次,f(x) - g(x)xmid之间的xhigh变化,我们会xlow = xmid切掉我们不是感兴趣的。我们得到:

       f(x)  g(x)
         /--
       -*
     --/

      ^    ^
      |    |
      xlow xhigh

同样,同样的问题,除了我们缩小了解决方案可能减半的范围。

在while循环中重复这一点,|f(xmid) - g(xmid)|几乎为零(比如小于0.000001(或1e-6)(也要注意绝对值))。在这种情况下,我们停止搜索,我们说那个特定的xmid就是答案。 (参见here我们为什么不检查是否平等,但是接近)。


还有一个问题。根据您的特定功能,可能会有许多横截面。我们如何找到xlowxhigh?好吧,我们希望范围[xlow, xhigh]只包含一个解决方案。因此,我们可以逐步找到这些范围并找到它们之间的横截面。

假设a > 0(和x > 0的解决方案),这就是图表的样子:

                              ----- f(x) = ax
   _           _         __*__         _ g(x) = sin(x)
  / \         /_*___----- / \         /
 /   *____---*-  \       /   \       /
|---- |     |     |     |     |     |
      |     |     |     |     |     |
       \   /       \   /       \   /
        \_/         \_/         \_/

让我们看看解决方案的位置。当然,它不在sin(x) < 0的位置。然后在[2kπ, 2kπ + π/2][2kπ + π/2, 2kπ + π]上,可以分别成为一个解决方案。初始[0, π / 2]可能有也可能没有解决方案,具体取决于a。因此,最安全的方法是枚举所有此类范围,为f(x) - g(x)xlow计算xhigh并查看其符号。如果标志没有改变,则没有解决方案,我们可以继续前进。如果确实发生了变化,我们会执行上面的二进制搜索。

算法什么时候结束?我们知道g(x) = sin(x) <= 1我们知道a > 0f(x) = ax总是在增加。所以当你有f(xlow) > 1时,肯定没有更多的解决方案。

算法将是:

Main Algorithm:
for k = 0,1,...
    xlow = 2kπ
    xhigh = 2kπ + π/2
    binary_search(xlow, xhigh)

    xlow = 2kπ + π/2
    xhigh = 2kπ + π
    binary_search(xlow, xhigh)

binary_search:
if axlow-sin(xlow) and axhigh-sin(xhigh) have the same sign
    return no result in this range
do
    xmid = (xhigh + xlow) / 2
    diff = axmid - sin(axmid)
    if diff and axlow-sin(xlow) have the same sign
        xlow = xmid
    else
        xhigh = xmid
while abs(diff) > epsilon
return xmid

对于a < 0的情况,解决方案类似(范围更改为sin周期的另一半)。顺便说一句,对于您在上面找到的每个x-x也是一个解决方案!

答案 1 :(得分:0)

显然,只有

的解决方案
-1 <= ax <= 1

差函数h(x)= sin(x)-ax的单调性在导数h'(x)= cos(x)-a的根之间的所有区间上是相同的,并且它们也是此函数的局部最大值和最小值。所以使用点

arccos(a), 2*pi-arccos(a), 2*pi+arccos(a), 4*pi-arccos(a), 4*pi+arccos(a), ...

只要它们小于1 / abs(a)来定义搜索间隔。根据Shahbaz的答案,二分法,或者更好的伊利诺斯式的falsi法的变体,在每一个里面使用。

答案 2 :(得分:-1)

没有任何优化的粗暴方法(因此是一种天真的方法)将在x上运行for循环,x从0运行到2 * PI,PI = 22.0 / 7.0,并且如果得到abs,则循环增量为0.001 (sin(x) - a * x)&lt; epsilon,epsilon所说的等于某些kow值,如0.001(取决于你的粒度),你得到它!这将解决你的等式sin(x)= a * x