程式設計科學/Auld Lang Sine
你很可能之前已經接觸過正弦和餘弦。正弦曲線(包括正弦和餘弦)是週期函式。週期函式具有以下性質
對於所有x 和p 的某些值。滿足上述等式的p 的最小值被稱為該函式的週期。
如果你不熟悉正弦和餘弦函式,這就是正弦波的樣子

請注意,對於沒有相位和頻率偏移的正弦波(如上所示),當x 為零時,正弦波的振幅(y 值)為零(具有上升斜率)。該波在x = 2 再次達到零(具有上升斜率)π. 對比餘弦波

與正弦波不同,正弦波在p 的倍數處具有零交叉點π,餘弦波在p 的倍數處具有峰值和谷值π. 與正弦波一樣,週期或峰值到峰值長度為 2π.
如果你仔細觀察這兩個波,你會發現餘弦只是正弦波向左移動了 個單位。因此,我們可以用正弦來定義餘弦
請注意,數學家通常將正弦縮寫為sin,將餘弦縮寫為cos。以上說明了修改正弦波的常見方法之一:移動波的相位,通常使用符號
另一種修改是改變正弦波的振幅,或者換句話說,改變峰值的高低範圍。變數a 用於表示振幅,因此允許振幅修改的正弦波公式為
最後,通常會改變正弦波的頻率,或者在給定區域內有多少個峰值(或谷值)。變數通常用於此任務
如果我們將 設定為 2,我們將獲得給定區域內兩倍的峰值(或谷值)。頻率的倒數是週期,因此將 設定為 2 將使峰值到峰值距離縮短一半。在頻率為 2 的特定情況下,正弦波的週期將為π.
這裡有一個巧妙的技巧。如果你想找到這種形式的一般符號波的“第一個”零交叉點的位置,請更改相移和將它與x 相結合的運算子的符號,然後將 提取出來。對於餘弦,具有單位振幅和頻率加倍,我們有
此版本的餘弦在 處具有第一個零交叉點。[1] 換句話說,要找到第一個零交叉點,請將相移除以頻率並取反(假設相移被新增進去)。
Sway 內建了sin 和cos 函式,但這些函式假設振幅 = 1,頻率 = 1 且相移 = 0。[2] 為了實現sine 和cosine,我們將採用我們通常的物件方法
function sine(amp,freq,shift)
{
function value(x)
{
amp * sin(freq * x + shift);
}
this;
}
function cosine(amp,freq,shift)
{
sine(amp,freq,shift + (pi() / 2));
}
請注意,我們如何將餘弦包裝為正弦,因為餘弦只是具有相移的正弦。
讓我們利用我們在上一節中學習的關於查詢“第一個”零交叉點的技巧,並將其實現
function sine(amp,freq,shift)
{
function value(x) { ... }
function firstZero()
{
// phase shift is added in so just divide and negate
-(real(shift) / freq);
}
this;
}
讓我們看看它是否適用於頻率為 2 的餘弦
var w = cose(1,2,0);
sway> -(pi() / 4);
REAL_NUMBER: -0.7853981634
sway> w . firstZero();
REAL_NUMBER: -0.7853981634
不錯。讓我們也檢查一下正弦波的值在該點確實為零
sway> var fz = w . firstZero();
REAL_NUMBER: -0.7853981634
sway> w . value(fz);
w . value(fz) is 0.000000e+00
bingo!
正如 SPT 在 CMT 的第 XV 章中指出的那樣,正弦的導數是餘弦,餘弦的導數是正弦的負數。
使用第一個規則,我們可以將diff 函式新增到sine 建構函式中。當然,為了符合我們謙遜的微分系統,我們需要根據需要傳入自變數和關於變數
function sine(amp,freq,shift)
{
function value(x) { ... }
function firstZero() { ... }
function diff()
{
cosine(amp,freq,shift);
}
this;
}
當然,此實現假定自變數和關於變數是一樣的。它還假定自變數只是一個符號。因此,我們無法構造形式為;
為此,我們將不得不像處理項一樣,允許自變數成為可微分物件。回想一下項建構函式
function term(a,iv,n)
{
function value(x) { ... }
function toString() { ... }
function diff(wrtv)
{
if (n == 0)
{
constant(0);
}
else
{
term(a * n,iv,n - 1) times iv . diff(wrtv);
}
}
if (iv is :SYMBOL) { iv = variable(iv); }
this;
}
還記得diff 函式如何實現鏈式法則。我們將需要對sine 建構函式採用相同的策略
function sine(amp,freq,iv,shift)
{
function value(x) { ... }
function firstZero() { ... }
function diff(wrtv)
{
cosine(amp,freq,iv,shift) times iv . diff(wrtv);
}
if (iv is :SYMBOL,iv = variable(iv));
this;
}
我們剩下要做的就是實現sine 的視覺化(當然還有測試)
function toString()
{
"" + amp +
" sin(" + freq +
"(" + iv . toString() + ")"
+ shift + ")";
}
根據 CMT,正弦函式的導數是餘弦函式,餘弦函式的導數是負正弦函式。因此,正弦函式的二階導數是負正弦函式。
1. 函式 和函式 之間有什麼區別?
2. 為什麼我們不能將 正弦 和 餘弦 建構函式命名為 sin 和 cos?
3. 在 正弦 建構函式中新增以下簡化。如果相移等於或大於 2π,減去 2π.
4. 解釋為什麼之前的簡化在數學上是有效的。
5. 簡化正弦物件的構造,以便如果幅度為零,則生成零物件。
6. 簡化正弦物件的構造,以便如果頻率為零,則生成常數項物件。
7. 簡化正弦物件的視覺化,以便如果幅度、頻率和相移分別為 1、1 和 0,則省略它們。
8. 查詢並新增其他視覺化調整。提示:如果頻率 ≠ 1 但自變數是係數 ≠ 1 的項,你的視覺化應該是什麼樣子?