我尝试用不同的方式解这个方程,但没有成功:
求两个函数的点数。
f(x) = sin(x)
y = a
在给定的a。在这种情况下,我们可以说 a = 0.15
sin(x) = ax
= 0.15x
x = sin(x)/0.15
???
谁能帮忙解答一下这个问题吗?
这就是问题的原话:
编写一个 C 程序,读取值 a 并写出方程 sin(x) = a*x
的所有解(即根)
注意:该方程肯定有一个解:x = 0
。但是,对于 a
的低值,代表方程 y = a*x
的线足够接近水平线以多次穿过正弦波。您的程序应该计算并打印根的数量及其值。
提示:假设您要解方程 f(x) = 0
,其中f(x)
是连续函数。进一步假设您可以找到两个值 xlow
和xhigh
这样f(xlow) < 0
和f(xhigh) > 0
和函数 f(x)
在这些值之间的某个位置仅穿过 x 轴一次。您可以继续使用所谓的“二分搜索”技术,如下所示:
- Estimate the solution x as x = (xlow + xhigh) / 2.0
- If |f(x)| < epsilon then print x as solution and exit; else
- If f(x) < 0 then substitute xlow = x else substitute xhigh = x
- Go to (1)
使用 epsilon = 0.001
最佳答案
You could proceed using the so called "binary search" technique
这是解决问题的关键。实际上它就是解决方案。让我画两个函数:
f(x) g(x)
/ --
/ --
/ --
/ --
/--
-*
--/
-- /
-- /
^ ^
| |
xlow xhigh
您有xlow
和xhigh
作为对哪里 f(x)
的估计十字架g(x)
。在你的问题中,f(x) = ax
和g(x) = sin(x)
.
首先,让我们看看为什么 xlow
和xhigh
做出一个好的估计。如果您注意到,请访问xlow
,我们有f(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
之间和xlow
,函数改变了big-ness-ship(换句话说,f(x) - g(x)
改变了它的符号),那么答案肯定在xlow
之间。和xmid
(请注意, xmid
和 xhigh
之间仍然可能存在偶数个解,但我们目前无法真正判断)。
所以,如果我们分配 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 了解为什么我们不检查相等性,而是检查接近性)。
还有一个问题。对于您的特定功能,可能会有许多横截面。我们如何找到xlow
和xhigh
?好吧,我们想要范围 [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 > 0
, f(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
也是一个解决办法!
关于c - 如何解决这个: two functions x = sin(x)/a,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22377923/